Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 为什么这个子选择有效?不适用于本条款_Sql_Postgresql_Sql Update - Fatal编程技术网

Sql 为什么这个子选择有效?不适用于本条款

Sql 为什么这个子选择有效?不适用于本条款,sql,postgresql,sql-update,Sql,Postgresql,Sql Update,我在编写PostgreSQL请求时犯了一个愚蠢的错误。语法似乎完全错误,但仍有一半的效果 我有这个表(订户): 还有其他行,但它们是唯一相关的行(具有相同的设备\u id) 我提出请求: UPDATE subscriber SET invert = false WHERE device_id = (SELECT device_id WHERE id = 1) RETURNING *; 我忘记了子选择的子句中的。子系统按预期选择自身崩溃(设备\u id不存在)。但是,完整请求将计算并

我在编写PostgreSQL请求时犯了一个愚蠢的错误。语法似乎完全错误,但仍有一半的效果

我有这个表(订户):

还有其他行,但它们是唯一相关的行(具有相同的
设备\u id

我提出请求:

UPDATE subscriber 
   SET invert = false 
WHERE device_id = (SELECT device_id WHERE id = 1) 
RETURNING *;
我忘记了子选择的
子句中的
。子系统按预期选择自身崩溃(
设备\u id不存在
)。但是,完整请求将计算并更新并返回其中一行(id为1的行)。正确的请求应该更新并返回两行


为什么??是某种虫子吗?或者子选择的行为是否与选择不同

我想以前也有人问过类似的问题,但我现在找不到

在子查询中,从外部查询中选择所有内容也是可见的。如果子选择中存在名称冲突,“本地”标识符优先于“外部”标识符。如果标识符在子选择中无效,但在外部查询中可用,则使用外部查询中的标识符

Postgres允许SELECT语句不带
FROM
子句,因此

select 42;
有效

因此,您的子选择实际上使用了正在更新的表中的
device\u id
id
列。这就是查询工作的原因


这不是一个bug,这些可见性规则是SQL标准所要求的(但是,运行
SELECT
而不运行
FROM
是对SQL标准的扩展)。

恐怕,跳过
FROM
您在括号中创建的表达式是一个相关的子查询,而不仅仅是子查询,例如:

t=# select oid,(select oid) from pg_database limit 2;
  oid  |  oid
-------+-------
     1 |     1
 12945 | 12945
(2 rows)
通过这种方式,Postgres尝试猜测列名使用的别名,在我的例子中,这是pg_数据库的别名。。。因此,在本例中,您的
where device_id=(选择device_id where id=1)
在逻辑上等于
where id=1

另一个例子:

t=# select oid,(select oid::int*2 where oid=1),2 from pg_database limit 2;
  oid  | ?column? | ?column?
-------+----------+----------
     1 |        2 |        2
 12945 |          |        2
(2 rows)

这是查询背后的一些奇怪的边缘逻辑。我不能不同意在您的update语句中这样的逻辑令人困惑:)
t=# select oid,(select oid::int*2 where oid=1),2 from pg_database limit 2;
  oid  | ?column? | ?column?
-------+----------+----------
     1 |        2 |        2
 12945 |          |        2
(2 rows)