Вставить в ... значения (ВЫБРАТЬ ... ИЗ ...)

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

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

этот пример работает: вставить в tag_zone select @ tag, zoneid, GETDATE (), @ positiong.STIntersects (polygon) from zone

Uğur Gümüşhan 03.01.2013 11:33
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1 542
1
2 746 247
26
Перейти к ответу Данный вопрос помечен как решенный

Ответы 26

Ответ принят как подходящий

Пытаться:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

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

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

  • Oracle
  • MS SQL Server
  • MySQL
  • Postgres
  • SQLite v3
  • Терадата
  • DB2
  • Sybase
  • Vertica
  • HSQLDB
  • H2
  • AWS RedShift
  • SAP HANA
  • Google Spanner

Ответ Клода Уля: должно работать нормально, и вы также можете иметь несколько столбцов и другие данные:

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.

что, если условие where изменено на table2.country и возвращает количество строк больше единицы? У меня аналогичная проблема: stackoverflow.com/questions/36030370/…

VijayRana 17.03.2016 09:25

Проблем со вставкой более одной строки быть не должно.

rinukkusu 11.04.2016 10:24

Обязательно ли вставлять во все столбцы таблицы

maheshmnj 24.02.2020 10:22

@maheshmnj нет, только столбцы, для которых установлено значение NOT NULL, и не нужно включать значение по умолчанию, для любых других столбцов будут установлены значения по умолчанию или NULL

travis 24.02.2020 19:49

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

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

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;

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

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

INSERT INTO table1
SELECT  col1, col2
FROM    table2

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

INSERT INTO table1
SELECT  col1
FROM    table2

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

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

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

Google: insert site: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.

Я полностью не согласен, я годами изучал эти синтаксические утверждения и до сих пор не могу понять их. Примеры намного полезнее

reggaeguitar 23.01.2020 21:00

Это не ответ, он говорит «прочтите документацию», и это все.

reggaeguitar 23.01.2020 21:05

На самом деле я предпочитаю в 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 (), и вы просто выбираете, какие значения должны быть в таблице.

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

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

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

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

insert into table1 select * from table2

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

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

Просто для пояснения: это неверно для SQLite3. Согласно документация, исходные данные для INSERT - это либоVALUES или оператор SELECT, но не оба одновременно.

user909694 23.07.2014 18:16

Это правда, что в документации это не указано, но это работает. Тем не менее, я думаю, что использование оператора select вместо значений делает его более читабельным.

Banjocat 21.10.2014 19:32

Он работает для указания значения внутри строки, но в более общем случае требуется получить много строк.

Luchostein 24.11.2015 17:33

Если val_1 не изменяется по строкам, то следующий синтаксис может работать в SQLite3? выберите 'foo', some_column из some_table - работает в SQLServer 2014

Chris B 16.09.2016 03:28

В документации это перечислено (сейчас?): Этот синтаксис - INSERT INTO ... VALUES ([expr], [expr], ...), а один из путей в [expr] - {{NOT} EXISTS} ([select-stmt]) - обратите внимание, что скобки вокруг оператора select обязательны ({} означает необязательный)

zapl 03.07.2018 21:06

что, если выбор вернет более 1 строки?

LeeR 18.11.2018 07:43

@Lee Это отличный вопрос. Я думаю, что когда я работал с этим val2, возможно, он был ПК или какой-то другой уникальной областью, поэтому он никогда не появлялся.

kylieCatt 30.11.2018 01:16

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

    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

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

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

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

INSERT INTO table1(desc, id, email) 
SELECT "Hello World", 3, email FROM table2 WHERE ...

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

Sebastian Kaczmarek 17.05.2018 13:23

select *
into tmp
from orders

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

Чтобы вставить в существующую таблицу 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

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

INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4) 
VALUES (value1, value2, 
(SELECT COLUMN_TABLE2 
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);

Этот подход применим только к такому подзапросу, в котором выбран только один столбец. В случае подзапроса с несколькими столбцами возникает ошибка «подзапрос должен возвращать только один столбец». Тогда примите ответ @travis.

snowfox 26.04.2016 05:10

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

INSERT INTO table1 ( column1 , 2, 3... )
SELECT col1, 2, 3... FROM table2

INSERT INTO yourtable
SELECT fielda, fieldb, fieldc
FROM donortable;

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

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

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'

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

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

SELECT  *
INTO    Table2
FROM    Table1;

Если вы перейдете по маршруту 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», и вы в конечном итоге напишете тривиальный пост, когда наконец выясните, что с этим делать.

Вопрос в том, «вставить в таблицу по входу из другого стола». Как ваш ответ отвечает на этот вопрос?

Quality Catalyst 21.11.2017 08:34

Эх, не будь с ним слишком суров. Он ответил на мой вопрос, когда я искал в Google. @QualityCatalyst

Darth Scitus 15.02.2018 18:19

INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT  COLUMN_NAME
FROM    ANOTHER_TABLE_NAME 
WHERE CONDITION;

@ggorlen Мне это кажется самоочевидным

reggaeguitar 19.04.2019 19:38

Он был помечен в очереди на проверку как ответ, содержащий только код. Однако я могу понять вашу точку зрения - теперь, когда я вижу это в естественной среде, в контексте большинства ответов на этой странице особо нечего сказать.

ggorlen 19.04.2019 19:48

Лучший способ вставить несколько записей из любых других таблиц.

INSERT  INTO dbo.Users
            ( UserID ,
              Full_Name ,
              Login_Name ,
              Password
            )
            SELECT  UserID ,
                    Full_Name ,
                    Login_Name ,
                    Password
            FROM    Users_Table
            (INNER JOIN / LEFT JOIN ...)
            (WHERE CONDITION...)
            (OTHER CLAUSE)

Просто используйте круглые скобки для предложения ВЫБРАТЬ в INSERT. Например так:

INSERT INTO Table1 (col1, col2, your_desired_value_from_select_clause, col3)
VALUES (
   'col1_value', 
   'col2_value',
   (SELECT col_Table2 FROM Table2 WHERE IdTable2 = 'your_satisfied_value_for_col_Table2_selected'),
   'col3_value'
);

Два подхода для вставки в с помощью подзапроса выбора.

  1. С подзапросом SELECT, возвращающим результаты с Один ряд.
  2. С подзапросом SELECT, возвращающим результаты с Несколько строк.

1. Подход для подзапроса With SELECT, возвращающего результаты с один ряд.

INSERT INTO <table_name> (<field1>, <field2>, <field3>) 
VALUES ('DUMMY1', (SELECT <field> FROM <table_name> ),'DUMMY2');

В этом случае предполагается, что подзапрос SELECT возвращает только одну строку результата на основе условия WHERE или агрегатных функций SQL, таких как SUM, MAX, AVG и т. д. В противном случае он выдаст ошибку.

2. Подход с подзапросом With SELECT, возвращающим результаты с несколько строк.

INSERT INTO <table_name> (<field1>, <field2>, <field3>) 
SELECT 'DUMMY1', <field>, 'DUMMY2' FROM <table_name>;

Второй подход будет работать в обоих случаях.

В informix это работает, как сказал Клод:

INSERT INTO table (column1, column2) 
VALUES (value1, value2);    

Postgres поддерживает следующее: создать таблицу company.monitor2 как select * from company.monitor;

ЕСЛИ вы хотите вставить некоторые данные в таблицу, не желая писать имя столбца.

INSERT INTO CUSTOMER_INFO
   (SELECT CUSTOMER_NAME,
           MOBILE_NO,
           ADDRESS
      FROM OWNER_INFO cm)

Где находятся таблицы:

            CUSTOMER_INFO               ||            OWNER_INFO
----------------------------------------||-------------------------------------
CUSTOMER_NAME | MOBILE_NO | ADDRESS     || CUSTOMER_NAME | MOBILE_NO | ADDRESS 
--------------|-----------|---------    || --------------|-----------|--------- 
      A       |     +1    |   DC        ||       B       |     +55   |   RR  

Результат:

            CUSTOMER_INFO               ||            OWNER_INFO
----------------------------------------||-------------------------------------
CUSTOMER_NAME | MOBILE_NO | ADDRESS     || CUSTOMER_NAME | MOBILE_NO | ADDRESS 
--------------|-----------|---------    || --------------|-----------|--------- 
      A       |     +1    |   DC        ||       B       |     +55   |   RR
      B       |     +55   |   RR        ||

Другие вопросы по теме