1802 votes

Insérer dans ... des valeurs ( SELECT ... FROM ... )

J'essaie de INSERT INTO une table en utilisant l'entrée d'une autre table. Bien que cela soit tout à fait réalisable pour de nombreux moteurs de base de données, j'ai toujours du mal à me souvenir de la syntaxe correcte de la fonction SQL le moteur du jour ( MySQL , Oracle , SQL Server , Informix et DB2 ).

Existe-t-il une syntaxe miracle issue d'une norme SQL (par exemple, SQL-92 ) qui me permettrait d'insérer les valeurs sans me soucier de la base de données sous-jacente ?

2 votes

Cet exemple fonctionne : insérer dans tag_zone select @tag,zoneid,GETDATE(),@positiong.STIntersects(polygon) from zone

1987voto

Shadow_x99 Points 10421

Essayez :

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

Il s'agit d'un langage SQL ANSI standard qui devrait fonctionner avec n'importe quel SGBD.

Ça marche vraiment pour :

  • Oracle
  • MS SQL Server
  • MySQL
  • Postgres
  • SQLite v3
  • Teradata
  • DB2
  • Sybase
  • Vertica
  • HSQLDB
  • H2
  • AWS RedShift
  • SAP HANA
  • Google Spanner

0 votes

Comment mettre cela en œuvre ? "insert into Content as c (ContentP) select title from title as t wehre c.pageno = t.pageno" . Merci

0 votes

Je doute fort qu'ils le supportent tous immédiatement - seul SQLite a une version minimale, mais ce serait également intéressant pour les autres, notamment ORACLE.

0 votes

@MindRoasterMir Vous ne pouvez pas faire ça. Si vous effectuez une insertion, vous créez une nouvelle ligne dans la table et vous ne pouvez donc pas avoir de ligne existante avec laquelle vous pouvez comparer (c.pageno = t.pageno). Vous recherchez probablement une UPDATE ou une MERGE (MS Sql).

1212voto

travis Points 14676

La réponse de Claude Houle : devrait fonctionner correctement, et vous pouvez également avoir plusieurs colonnes et d'autres données :

INSERT INTO table1 ( column1, column2, someInt, someVarChar )
SELECT  table2.column1, table2.column2, 8, 'some string etc.'
FROM    table2
WHERE   table2.ID = 7;

Je n'ai utilisé cette syntaxe qu'avec Access, SQL 2000/2005/Express, MySQL et PostgreSQL, qui devraient donc être couverts. Elle devrait également fonctionner avec SQLite3.

1 votes

Que se passe-t-il si la condition "where" est modifiée en table2.country et renvoie un nombre de lignes supérieur à un ? J'ai un problème similaire ici : stackoverflow.com/questions/36030370/

1 votes

Il ne devrait pas y avoir de problème pour insérer plus d'une ligne.

0 votes

Est-il nécessaire d'insérer dans toutes les colonnes du tableau ?

227voto

IanAuld Points 1894

Pour obtenir une seule valeur dans un ensemble de valeurs INSERT à partir d'une autre table, j'ai fait ce qui suit en SQLite3 :

INSERT INTO column_1 ( val_1, val_from_other_table ) 
VALUES('val_1', (SELECT  val_2 FROM table_2 WHERE val_2 = something))

4 votes

Juste pour clarifier : ceci est incorrect pour SQLite3. D'après la documentation les données de base pour le INSERT est soit VALUES ou un SELECT mais pas les deux.

2 votes

Il est vrai que la documentation ne le mentionne pas, mais cela fonctionne. Quoi qu'il en soit, je pense que l'utilisation de l'instruction select au lieu de valeurs rend le texte plus lisible.

2 votes

Cela fonctionne pour spécifier une valeur à l'intérieur d'une ligne, mais le cas plus général nécessite d'obtenir beaucoup de lignes.

75voto

Jonathan Leffler Points 299946

Les deux réponses que je vois fonctionnent bien dans Informix spécifiquement, et sont fondamentalement du SQL standard. C'est-à-dire, la notation :

INSERT INTO target_table[(<column-list>)] SELECT ... FROM ...;

fonctionne bien avec Informix et, je pense, avec tous les SGBD. (Il y a 5 ans ou plus, c'est le genre de choses que MySQL ne supportait pas toujours ; il a maintenant un support décent pour ce genre de syntaxe SQL standard et, AFAIK, il fonctionnerait bien avec cette notation). La liste des colonnes est facultative mais elle indique les colonnes cibles dans l'ordre, de sorte que la première colonne du résultat du SELECT ira dans la première colonne listée, etc. En l'absence de liste de colonnes, la première colonne du résultat du SELECT est placée dans la première colonne de la table cible.

Ce qui peut différer d'un système à l'autre, c'est la notation utilisée pour identifier les tables dans les différentes bases de données. La norme ne dit rien sur les opérations entre bases de données (et encore moins entre SGBD). Avec Informix, vous pouvez utiliser la notation suivante pour identifier une table :

[dbase[@server]:][owner.]table

C'est-à-dire que vous pouvez spécifier une base de données, en identifiant éventuellement le serveur qui héberge cette base de données si elle n'est pas dans le serveur actuel, suivi d'un propriétaire facultatif, d'un point, et enfin du nom de la table réelle. La norme SQL utilise le terme schéma pour ce qu'Informix appelle le propriétaire. Ainsi, dans Informix, l'une des notations suivantes pourrait identifier une table :

table
"owner".table
dbase:table
dbase:owner.table
dbase@server:table
dbase@server:owner.table

Le propriétaire en général n'a pas besoin d'être cité ; toutefois, si vous utilisez des guillemets, vous devez veiller à ce que le nom du propriétaire soit correctement orthographié - il est sensible à la casse. C'est-à-dire

someone.table
"someone".table
SOMEONE.table

tous identifient la même table. Avec Informix, il y a une légère complication avec les bases de données MODE ANSI, où les noms de propriétaires sont généralement convertis en majuscules (Informix est l'exception). C'est-à-dire que dans une base de données MODE ANSI (peu utilisée), vous pourriez écrire :

CREATE TABLE someone.table ( ... )

et le nom du propriétaire dans le catalogue du système serait "SOMEONE", plutôt que "someone". Si vous placez le nom du propriétaire entre guillemets doubles, il se comporte comme un identificateur délimité. Avec le langage SQL standard, les identificateurs délimités peuvent être utilisés à de nombreux endroits. Avec Informix, vous ne pouvez les utiliser qu'autour des noms de propriétaires -- dans d'autres contextes, Informix traite les chaînes entre guillemets simples et doubles comme des chaînes, plutôt que de séparer les chaînes entre guillemets simples comme des chaînes et les chaînes entre guillemets doubles comme des identificateurs délimités. (Bien sûr, juste pour être complet, il existe une variable d'environnement, DELIMIDENT, qui peut être définie - à n'importe quelle valeur, mais Y est la plus sûre - pour indiquer que les guillemets doubles entourent toujours les identificateurs délimités et les guillemets simples entourent toujours les chaînes de caractères).

Notez que MS SQL Server parvient à utiliser des [identificateurs délimités] entre crochets. Cela me semble bizarre et ne fait certainement pas partie de la norme SQL.

32voto

northben Points 1133

Cela peut être fait sans spécifier les colonnes dans le champ INSERT INTO si vous fournissez des valeurs pour toutes les colonnes de la base de données. SELECT partie.

Disons que le tableau 1 a deux colonnes. Cette requête devrait fonctionner :

INSERT INTO table1
SELECT  col1, col2
FROM    table2

Cela ne fonctionnerait PAS (valeur pour col2 n'est pas spécifié) :

INSERT INTO table1
SELECT  col1
FROM    table2

J'utilise MS SQL Server. Je ne sais pas comment fonctionnent les autres RDMS.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X