Вставить в ... значения (SELECT ... FROM ...) - PullRequest
1262 голосов
/ 25 августа 2008

Я пытаюсь INSERT INTO таблицу, используя данные из другой таблицы. Хотя это вполне выполнимо для многих механизмов баз данных, мне всегда трудно вспомнить правильный синтаксис для механизма SQL дня ( MySQL , Oracle , SQL Сервер , Informix и DB2 ).

Существует ли синтаксис «серебряной пули», исходящий из стандарта SQL (например, SQL-92 ), который позволил бы мне вставлять значения, не беспокоясь о базовой базе данных?

Ответы [ 23 ]

1445 голосов
/ 25 августа 2008

Попробуйте:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

Это стандартный ANSI SQL и должен работать на любой СУБД

Это определенно работает для:

  • Oracle
  • MS SQL Server
  • MySQL
  • Postgres
  • SQLite v3
  • Teradata
  • DB2
  • Sybase
  • Vertica
  • HSQLDB
  • H2
  • AWS RedShift
  • SAP HANA
840 голосов
/ 25 августа 2008

@ Shadow_x99 : это должно работать нормально, вы также можете иметь несколько столбцов и другие данные:

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

Edit: я должен упомянуть, что я использовал этот синтаксис только с Access, SQL 2000/2005 / Express, MySQL и PostgreSQL, поэтому они должны быть рассмотрены. Комментатор указал, что он будет работать с SQLite3.

109 голосов
/ 11 января 2014

Чтобы получить только одно значение в мультизначном значении INSERT из другой таблицы, я сделал следующее в SQLite3:

INSERT INTO column_1 ( val_1, val_from_other_table ) 
VALUES('val_1', (SELECT  val_2 FROM table_2 WHERE val_2 = something))
57 голосов
/ 28 сентября 2008

Оба ответа, которые я вижу, отлично работают в Informix, и в основном это стандартный SQL. То есть обозначение:

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

отлично работает с Informix и, как я ожидаю, со всеми СУБД. (Когда-то 5 или более лет назад, MySQL не всегда поддерживал такую ​​ситуацию; теперь он имеет достойную поддержку для такого рода стандартного синтаксиса SQL и, AFAIK, будет работать нормально в этой записи.) Список столбцов является необязательным, но указывает целевые столбцы в последовательности, поэтому первый столбец результата SELECT перейдет в первый перечисленный столбец и т. д. При отсутствии списка столбцов первый столбец результата SELECT перейдет в первый столбец целевой таблицы.

Что может отличаться в разных системах, так это нотация, используемая для идентификации таблиц в разных базах данных - стандарт не имеет ничего общего с операциями между базами данных (не говоря уже о между-СУБД). С Informix вы можете использовать следующие обозначения для идентификации таблицы:

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

То есть вы можете указать базу данных, опционально идентифицируя сервер, на котором размещена эта база данных, если его нет на текущем сервере, за которым следует необязательный владелец, точка и, наконец, фактическое имя таблицы. Стандарт SQL использует термин схема для того, что Informix называет владельцем. Таким образом, в Informix любые из следующих обозначений могут идентифицировать таблицу:

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

Владелец вообще не должен быть указан; однако, если вы используете кавычки, вам нужно правильно написать имя владельца - оно становится чувствительным к регистру. То есть:

someone.table
"someone".table
SOMEONE.table

все идентифицируют одну и ту же таблицу. С Informix есть небольшое осложнение с базами данных MODE ANSI, где имена владельцев обычно преобразуются в верхний регистр (informix является исключением). То есть в базе данных MODE ANSI (обычно не используется) вы можете написать:

CREATE TABLE someone.table ( ... )

и имя владельца в системном каталоге будет «НЕКОТОРЫЙ», а не «кто-то». Если вы заключаете имя владельца в двойные кавычки, оно действует как идентификатор с разделителями. В стандартном SQL идентификаторы с разделителями могут использоваться во многих местах. В Informix вы можете использовать их только вокруг имен владельцев - в других контекстах Informix обрабатывает как одинарные, так и двойные кавычки как строки, а не разделяет одинарные кавычки как строки, а двойные кавычки - как идентификаторы с разделителями. (Конечно, просто для полноты есть переменная окружения DELIMIDENT, которую можно установить - любое значение, но Y - самый безопасный - чтобы указать, что двойные кавычки всегда окружают идентификаторы с разделителями, а одинарные кавычки всегда окружают строки.)

Обратите внимание, что MS SQL Server удается использовать [идентификаторы с разделителями], заключенные в квадратные скобки. Это выглядит странно для меня и, конечно, не является частью стандарта SQL.

29 голосов
/ 01 апреля 2013

Большинство баз данных следуют базовому синтаксису,

INSERT INTO TABLE_NAME
SELECT COL1, COL2 ...
FROM TABLE_YOU_NEED_TO_TAKE_FROM
;

Каждая база данных, которую я использовал, имеет следующий синтаксис: DB2, SQL Server, MY SQL, PostgresQL

29 голосов
/ 09 апреля 2015

Чтобы добавить что-то в первый ответ, когда нам нужно всего несколько записей из другой таблицы (в этом примере только одна):

INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4) 
VALUES (value1, value2, 
(SELECT COLUMN_TABLE2 
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);
23 голосов
/ 16 октября 2012

Это можно сделать без указания столбцов в части INSERT INTO, если вы задаете значения для всех столбцов в части SELECT.

Допустим, в table1 есть два столбца. Этот запрос должен работать:

INSERT INTO table1
SELECT  col1, col2
FROM    table2

Это НЕ БУДЕТ работать (значение для col2 не указано):

INSERT INTO table1
SELECT  col1
FROM    table2

Я использую MS SQL Server. Я не знаю, как работают другие RDMS.

20 голосов
/ 21 апреля 2015

Вместо VALUES части запроса INSERT, просто используйте запрос SELECT, как показано ниже.

INSERT INTO table1 ( column1 , 2, 3... )
SELECT col1, 2, 3... FROM table2
19 голосов
/ 20 марта 2014

Это еще один пример использования значений с select:

INSERT INTO table1(desc, id, email) 
SELECT "Hello World", 3, email FROM table2 WHERE ...
18 голосов
/ 13 февраля 2014

Простая вставка, когда известна последовательность столбцов таблицы:

    Insert into Table1
    values(1,2,...)

Простая вставка с упоминанием столбца:

    Insert into Table1(col2,col4)
    values(1,2)

Массовая вставка, когда количество выбранных столбцов таблицы (# table2) равно таблице вставки (Table1)

    Insert into Table1 {Column sequence}
    Select * -- column sequence should be same.
       from #table2

Массовая вставка, если вы хотите вставить только в нужный столбец таблицы (таблица1):

    Insert into Table1 (Column1,Column2 ....Desired Column from Table1)  
    Select Column1,Column2..desired column from #table2
       from #table2
...