37

给定一个foo具有复合主键的表(a,b),是否有用于编写查询的合法语法,例如:

SELECT ... FROM foo WHERE a,b IN (SELECT ...many tuples of a/b values...);
UPDATE foo SET ... WHERE a,b IN (SELECT ...many tuples of a/b values...);

如果这是不可能的,并且您无法修改架构,那么您如何执行与上述等效的操作?

我还将在此处放置术语“复合主键”、“子选择”、“子选择”和“子查询”,以查找这些别名的搜索命中。

编辑:我对标准 SQL 的答案以及适用于 PostgreSQL 和 SQLite 3 的答案感兴趣。

4

9 回答 9

27
sqlite> create table foo (a,b,c);
sqlite> create table bar (x,y);
sqlite> select * from foo where exists (select 1 from bar where foo.a = bar.x and foo.b = bar.y);

将 替换为select 1 from bar您的select ... many tuples of a/b values ....

或创建您的临时表select ... many tuples of a/b values ...并使用它来代替bar..

于 2011-01-07T04:31:32.383 回答
24

您的语法非常接近标准 SQL!

以下是有效的 FULL SQL-92(由Mimer SQL-92 Validator确认)

SELECT * 
  FROM foo 
  WHERE (a, b) IN (
                   SELECT a, b 
                      FROM bar
                  );

当然,并不是每个 SQL 产品都支持完整的 SQL-92(耻辱!)如果有人想看到 Microsoft SQL Server 支持这种语法,他们可以在这里投票。

更广泛支持的另一种 SQL-92 结构(例如,由 Microsoft SQL Server 和 Oracle)是INTERSECT例如

SELECT a, b
  FROM Foo
INTERSECT
SELECT a, b
  FROM Bar;

请注意,这些构造可以正确处理该NULL值,这与此处的其他一些建议不同,例如使用EXISTS (<equality predicates>)、 连接值等的建议。

于 2011-01-07T11:27:52.383 回答
11

你犯了一个很小的错误。您必须将 a,b 放在括号中。

SELECT ... FROM foo WHERE (a,b) IN (SELECT f,d FROM ...);

这样可行!

于 2012-08-01T13:04:07.460 回答
4

您建议的 IN 语法不是有效的 SQL。使用 EXISTS 的解决方案应该适用于所有合理兼容的 SQL RDBMS:

 UPDATE foo SET x = y WHERE EXISTS
    (SELECT * FROM bar WHERE bar.c1 = foo.c1 AND bar.c2 = foo.c2)

请注意,这通常不是特别有效。

于 2011-01-07T04:52:37.880 回答
3
    SELECT ...
      FROM foo
INNER JOIN (SELECT ...many tuples of a/b values...) AS results
        ON results.a = foo.a
       AND results.b = foo.b

那就是你要找的东西?

于 2011-01-07T04:20:01.080 回答
1

通过串联,这适用于 PostgreSQL:

SELECT a,b FROM foo WHERE a||b IN (SELECT a||b FROM bar WHERE condition);

UPDATE foo SET x=y WHERE a||b IN (SELECT a||b FROM bar WHERE condition);
于 2011-01-07T10:24:23.500 回答
0

如果您需要一个不需要表中已经存在的值的元组的解决方案,您可以连接列表中的相关表值和项目,然后使用“IN”命令。

在 postgres 中,这看起来像这样:

SELECT * FROM foo WHERE a || '_' || b in ('Hi_there', 'Me_here', 'Test_test');

在 SQL 中,我想它可能看起来像这样:

SELECT * FROM foo WHERE CONCAT(a, "_", b) in ('Hi_there', 'Me_here', 'Test_test');

于 2012-11-09T05:29:46.087 回答
0

JOINS并且INTERSECTS作为 的替代品工作得很好IN,但它们不像替代品那么明显NOT IN,例如:将行从它们不存在的地方插入TableA到两个表上的组合中。TableBTableBPK

我目前在 SQL Server 中使用上面的连接方法,但这不是一个非常优雅的解决方案。

于 2011-04-05T12:45:56.723 回答
0

Firebird uses this concatenation formula:

SELECT a,b FROM foo WHERE a||b IN (SELECT a||b FROM bar WHERE condition);

于 2013-10-14T07:38:16.923 回答