Вставить в... значения (SELECT... FROM...)

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

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

+960
источник поделиться
20 ответов

Try:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

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

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

  • Oracle
  • MS SQL Server
  • MySQL
  • Postgres
  • SQLite v3
  • Teradata​​li >
  • DB2
  • Sybase
  • Vertica
  • HSQLDB
  • Н2
  • AWS RedShift
  • SAP HANA
+1143
источник

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

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

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

+721
источник
другие ответы

Связанные вопросы


Похожие вопросы

Чтобы получить только одно значение в многозначном значении 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))
+66
источник

Оба ответа, которые я вижу, отлично работают в 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
[email protected]:table
[email protected]:owner.table

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

someone.table
"someone".table
SOMEONE.table

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

CREATE TABLE someone.table ( ... )

а имя владельца в системном каталоге будет "ЧЕЛОВЕК", а не "кто-то". Если вы введете имя владельца в двойные кавычки, он будет действовать как разделительный идентификатор. Со стандартным SQL идентификаторы с разделителями могут использоваться во многих местах. В Informix вы можете использовать их только по именам владельцев - в других контекстах Informix рассматривает как строки с одиночными кавычками, так и строки с двойными кавычками в виде строк, вместо того, чтобы разделять строки с одним кадром как строки и строки с двумя кавычками в качестве идентификаторов с разделителями. (Разумеется, для полноты есть переменная среды DELIMIDENT, которая может быть установлена ​​на любое значение, но Y является самым безопасным - чтобы указать, что двойные кавычки всегда окружают разделительные идентификаторы, а одинарные кавычки всегда окружают строки.)

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

+45
источник

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

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

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

+23
источник

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

Предположим, что таблица1 имеет два столбца. Этот запрос должен работать:

INSERT INTO table1
SELECT  col1, col2
FROM    table2

Это НЕ РАБОТАЕТ (значение для col2 не указано):

INSERT INTO table1
SELECT  col1
FROM    table2

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

+21
источник

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

INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4) 
VALUES (value1, value2, 
(SELECT COLUMN_TABLE2 
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);
+20
источник

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

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

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

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

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

    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
+14
источник

Это еще один пример, использующий значения с выбором:

INSERT INTO table1(desc, id, email) 
SELECT "Hello World", 3, email FROM table2 WHERE ...
+11
источник

Здесь как вставить из нескольких таблиц. В этом конкретном примере вы найдете таблицу сопоставления во многих сценариях:

insert into StudentCourseMap (StudentId, CourseId) 
SELECT  Student.Id, Course.Id FROM Student, Course 
WHERE Student.Name = 'Paddy Murphy' AND Course.Name = 'Basket weaving for beginners'

(Я понимаю, что совпадение имени студента может возвращать несколько значений, но вы получаете идею. Согласование чего-то другого, кроме идентификатора, необходимо, когда Id является столбцом Identity и неизвестно.)

+10
источник
INSERT INTO yourtable
SELECT fielda, fieldb, fieldc
FROM donortable;

Это работает во всех СУБД

+9
источник

Вы можете попробовать это, если хотите вставить весь столбец, используя таблицу SELECT * INTO.

SELECT  *
INTO    Table2
FROM    Table1;
+9
источник

Для Microsoft SQL Server я рекомендую научиться интерпретировать SYNTAX, предоставленный в MSDN. С Google проще, чем когда-либо, искать синтаксис.

В этом конкретном случае попробуйте

Google: вставить сайт: microsoft.com

Первый результат будет http://msdn.microsoft.com/en-us/library/ms174335.aspx

прокрутите вниз до примера ( "Использование опций SELECT и EXECUTE для вставки данных из других таблиц" ), если вам трудно интерпретировать синтаксис, указанный в верхней части страницы.

[ WITH <common_table_expression> [ ,...n ] ]
INSERT 
{
        [ TOP ( expression ) [ PERCENT ] ] 
        [ INTO ] 
        { <object> | rowset_function_limited 
          [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]
        }
    {
        [ ( column_list ) ] 
        [ <OUTPUT Clause> ]
        { VALUES ( { DEFAULT | NULL | expression } [ ,...n ] ) [ ,...n     ] 
        | derived_table       <<<<------- Look here ------------------------
        | execute_statement   <<<<------- Look here ------------------------
        | <dml_table_source>  <<<<------- Look here ------------------------
        | DEFAULT VALUES 
        }
    }
}
[;]

Это должно быть применимо для любых доступных СУБД. Нет смысла запоминать весь синтаксис для всех продуктов IMO.

+8
источник

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

INSERT INTO table1 ( column1 , 2, 3... ) SELECT col1, 2, 3... FROM table2
+8
источник

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

INSERT INTO cesc_pf_stmt_ext_wrk( 
  PF_EMP_CODE    ,
  PF_DEPT_CODE   ,
  PF_SEC_CODE    ,
  PF_PROL_NO     ,
  PF_FM_SEQ      ,
  PF_SEQ_NO      ,
  PF_SEP_TAG     ,
  PF_SOURCE) 
SELECT
  PFl_EMP_CODE    ,
  PFl_DEPT_CODE   ,
  PFl_SEC         ,
  PFl_PROL_NO     ,
  PF_FM_SEQ       ,
  PF_SEQ_NO       ,
  PFl_SEP_TAG     ,
  PF_SOURCE
 FROM cesc_pf_stmt_ext,
      cesc_pfl_emp_master
 WHERE pfl_sep_tag LIKE '0'
   AND pfl_emp_code=pf_emp_code(+);

COMMIT;
+7
источник

Я действительно предпочитаю следующее в SQL Server 2008:

SELECT Table1.Column1, Table1.Column2, Table2.Column1, Table2.Column2, 'Some String' AS SomeString, 8 AS SomeInt
INTO Table3
FROM Table1 INNER JOIN Table2 ON Table1.Column1 = Table2.Column3

Это исключает шаг добавления набора Insert(), и вы просто выбираете, какие значения идут в таблице.

+7
источник

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

insert into table1 select * from table2

Предложение немного отличается от предложения Oracle.

+7
источник
select *
into tmp
from orders

Выглядит неплохо, но работает только в том случае, если tmp не существует (создает его и заполняет). (SQL sever)

Вставить в существующую таблицу tmp:

set identity_insert tmp on

insert tmp 
([OrderID]
      ,[CustomerID]
      ,[EmployeeID]
      ,[OrderDate]
      ,[RequiredDate]
      ,[ShippedDate]
      ,[ShipVia]
      ,[Freight]
      ,[ShipName]
      ,[ShipAddress]
      ,[ShipCity]
      ,[ShipRegion]
      ,[ShipPostalCode]
      ,[ShipCountry] )
      select * from orders

set identity_insert tmp off
+6
источник
  • Оператор INSERT INTO SELECT копирует данные из одной таблицы и вставляет его в другую таблицу.

  • INSERT INTO SELECT требует, чтобы типы данных в исходной и целевой таблицах соответствовали Существующие записи в целевой таблице не затронуты

INSERT INTO SELECT Синтаксис: -

INSERT INTO table2
SELECT * FROM table1
WHERE condition;

INSERT IN SEL SELECT Пример: -

INSERT INTO Customers (CustomerName, ContactName, Address, City, PostalCode, Country)
SELECT SupplierName, ContactName, Address, City, PostalCode, Country FROM Suppliers;
+1
источник

Если вы запустите маршрут INSERT VALUES, чтобы вставить несколько строк, обязательно разделите VALUES на группы с помощью круглых скобок, чтобы:

INSERT INTO `receiving_table`
  (id,
  first_name,
  last_name)
VALUES 
  (1002,'Charles','Babbage'),
  (1003,'George', 'Boole'),
  (1001,'Donald','Chamberlin'),
  (1004,'Alan','Turing'),
  (1005,'My','Widenius');

В противном случае объекты MySQL указывают, что "Количество столбцов не соответствует количеству значений в строке 1", и вы в конечном итоге пишете тривиальный пост, когда вы, наконец, выясните, что с ним делать.

0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос