Skip to content
Sarj Code Standards

no-select-star

SQL SELECT projections should list explicit result columns instead of wildcards.

Why

Wildcard projections can over-fetch data and silently change result contracts when a source schema evolves.

Fix

List the output columns required by the query consumer. Suppress with a rationale when a bounded intermediate relation intentionally preserves its complete shape.

Examples

Before — flagged Store query selects every column
app/call_store.py
row = cursor.execute(
"SELECT c.* FROM call AS c WHERE c.id = %s",
(call_id,),
).fetchone()
call = Call.model_validate(row)
After — preferred Store query selects named columns
app/call_store.py
row = cursor.execute(
"SELECT c.id, c.status FROM call AS c WHERE c.id = %s",
(call_id,),
).fetchone()
call = Call.model_validate(row)
Before — flagged Expand the authored columns of an owned literal relation
app/literal_rows.py
from psycopg import Connection
def literal_rows():
with Connection.connect() as connection:
return connection.execute(
'SELECT * FROM (VALUES (1, 2)) AS "authored"("a", "b")'
).fetchall()
After — preferred Preserve the explicit authored literal columns
app/literal_rows.py
from psycopg import Connection
def literal_rows():
with Connection.connect() as connection:
return connection.execute(
'SELECT "authored"."a", "authored"."b" FROM (VALUES (1, 2)) AS "authored"("a", "b")'
).fetchall()
Autofix output
app/literal_rows.py
from psycopg import Connection
def literal_rows():
with Connection.connect() as connection:
return connection.execute(
'SELECT "authored"."a", "authored"."b" FROM (VALUES (1, 2)) AS "authored"("a", "b")'
).fetchall()
Before — flagged The outer projection still selects every column
app/queries.py
query = "SELECT EXISTS((SELECT * FROM jobs)), * FROM runs"
After — preferred Quoted arithmetic operands do not project a wildcard
app/queries.py
query = 'SELECT "units" * "price" AS total FROM entries'