A partir d'une table foo
avec une clé primaire composite (a,b)
, existe-t-il une syntaxe légale pour écrire une requête telle que:
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...);
Si ce n'est pas possible et que vous ne pouvez pas modifier le schéma, comment pouvez-vous effectuer l'équivalent de ce qui précède?
Je vais aussi mettre les termes "clé primaire composée", "sous-sélection", "sous-sélection" et "sous-requête" pour les résultats de recherche relatifs à ces alias.
Edit : Je suis intéressé par les réponses pour le SQL standard ainsi que pour celles qui fonctionneraient avec PostgreSQL et SQLite 3.
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);
Remplacez le select 1 from bar
par votre select ... many tuples of a/b values ...
.
Ou créez une table temporaire de votre select ... many tuples of a/b values ...
et utilisez-la à la place de bar
..
Votre syntaxe est très proche de SQL standard!
Ce qui suit est valide FULL SQL-92 (comme confirmé par le validateur Mimer SQL-92 )
SELECT *
FROM foo
WHERE (a, b) IN (
SELECT a, b
FROM bar
);
Bien sûr, tous les produits SQL ne prennent pas totalement en charge le SQL-92 (dommage). Si quelqu'un souhaite que cette syntaxe soit prise en charge dans Microsoft SQL Server, il peut voter pour elle ici .
Une autre construction SQL-92 plus largement prise en charge (par exemple par Microsoft SQL Server et Oracle) est INTERSECT
par exemple.
SELECT a, b
FROM Foo
INTERSECT
SELECT a, b
FROM Bar;
Notez que ces constructions gèrent correctement la valeur NULL
, contrairement à certaines des autres suggestions présentées ici, par exemple. ceux qui utilisent EXISTS (<equality predicates>)
, les valeurs concaténées, etc.
Vous avez commis une très petite erreur… .. Vous devez mettre a, b entre parenthèses.
SELECT ... FROM foo WHERE (a,b) IN (SELECT f,d FROM ...);
Ça marche!
La syntaxe IN que vous avez suggérée n’est pas SQL valide. Une solution utilisant EXISTS doit s’appliquer à tous les SGBDRB SQL raisonnablement conformes:
UPDATE foo SET x = y WHERE EXISTS
(SELECT * FROM bar WHERE bar.c1 = foo.c1 AND bar.c2 = foo.c2)
Sachez que ce n'est souvent pas particulièrement performant.
SELECT ...
FROM foo
INNER JOIN (SELECT ...many tuples of a/b values...) AS results
ON results.a = foo.a
AND results.b = foo.b
C'est ce que vous cherchez?
Avec concaténation, cela fonctionne avec 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);
Firebird utilise cette formule de concaténation:
SÉLECTIONNEZ a, b FROM foo WHERE a | | b |
JOINS
et INTERSECTS
remplacent parfaitement IN
, mais pas aussi évident que NOT IN
, par exemple: insérer des lignes de TableA
dans TableB
alors qu'elles n'existent pas encore dans TableB
où PK
sur les deux tables est un composite .
J'utilise actuellement la méthode de concaténation ci-dessus dans SQL Server, mais ce n'est pas une solution très élégante.