WHERE col1,col2 IN(...)[使用复合主键的SQL子查询]

时间:2011-01-07 04:14:16

标签: sql subquery composite-primary-key

给定具有复合主键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...);

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

我还要在这里添加“复合主键”,“子选择”,“子选择”和“子查询”等术语,以便对这些别名进行搜索命中。 < / p>

编辑:我对标准SQL以及可以与PostgreSQL和SQLite 3一起使用的答案感兴趣。

9 个答案:

答案 0 :(得分:26)

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 ..

答案 1 :(得分:19)

您的语法非常接近标准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支持这种语法,他们可以投票支持here

更广泛支持的另一个SQL-92构造(例如,由Microsoft SQL Server和Oracle)INTERSECTSELECT a, b FROM Foo INTERSECT SELECT a, b FROM Bar;

NULL

请注意,这些结构可以正确处理EXISTS (<equality predicates>)值,这与此处的其他一些建议不同,例如:使用{{1}},连接值等的那些

答案 2 :(得分:9)

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

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

有效!

答案 3 :(得分: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)

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

答案 4 :(得分: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

那你在找什么?

答案 5 :(得分:2)

通过连接,这适用于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);

答案 6 :(得分:0)

JOINSINTERSECTS可以替代IN,但它们并不像NOT IN的替代品那样明显,例如:从{{插入行1}}进入TableA TableBTableB中两个表中的PK都是合成的。{/ p>

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

答案 7 :(得分: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');

答案 8 :(得分:0)

Firebird使用此连接公式:

  

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