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


1427

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

Чи є синтаксис сріблястої кулі зі стандарту SQL (наприклад, SQL-92 ), який би дозволив мені вставити значення, не турбуючись про базову базу даних?


1
цей приклад працює: вставити в tag_zone select @ tag, zoneid, GETDATE (), @ positiong.STІнтерсекти (полігон) із зони
Uğur Gümüşhan

Відповіді:


1611

Спробуйте:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

Це стандартний ANSI SQL і повинен працювати на будь-яких СУБД

Це безумовно працює для:

  • Oracle
  • MS SQL Server
  • MySQL
  • Постгрес
  • SQLite v3
  • Терадата
  • DB2
  • Sybase
  • Вертика
  • HSQLDB
  • Н2
  • AWS RedShift
  • САП ХАНА

946

Відповідь Клода Хоула : має працювати добре, а також ви можете мати кілька стовпців та інші дані:

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.


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

1
Не повинно виникнути проблем із вставленням більше одного рядка.
rinukkusu

чи потрібно, щоб ми вставили у всі стовпці таблиці
maheshmnj

1
@maheshmnj ні, потрібно включати лише стовпці, які встановлені на NULL і не мають значення за замовчуванням, будь-які інші стовпці будуть встановлені за замовчуванням або NULL
travis

спасибі за інформацію
maheshmnj

148

Щоб отримати лише одне значення в багатозначному значенні 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))

4
Просто для уточнення: це невірно для SQLite3. Відповідно до документації , вихідними даними для абоINSERT є, або твердження, а не обидва. VALUESSELECT

2
Це правда, документація не перераховує її, але вона працює. Незалежно від того, я думаю, що використання оператора select замість значень робить його більш читабельним.
Banjocat

1
Він працює для визначення значення всередині рядка, але більш загальний випадок вимагає отримання великої кількості рядків.
Luchostein

Якщо val_1 не змінюється в рядах, то наступний синтаксис може працювати в SQLite3? виберіть 'foo', some_column from some_table - працює в SQLServer 2014
Chris B

Документація робить список цей (тепер?): Цей синтаксис INSERT INTO ... VALUES ([expr], [expr], ...)і один із шляхів у [expr]є {{NOT} EXISTS} ([select-stmt])- до відома , що paranthesis навколо оператора вибору необхідна ( {}тобто по бажанню)
zapl

64

Обидва відповіді, як я бачу, добре працюють в 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.


40

Щоб додати щось у першій відповіді, коли нам потрібно лише кілька записів з іншої таблиці (у цьому прикладі лише одну):

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

4
Цей підхід застосовується лише до такого підзапиту, що вибрано лише один стовпець. У випадку запиту з декількома стовпцями помилка "підзапит повинен повернути лише один стовпець". Тоді прийняти відповідь @ travis.
сніжинка

34

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

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

Кожна база даних я використовував такий синтаксис , а саме DB2, SQL Server, MY SQL,PostgresQL


34

Замість VALUESчастини INSERTзапиту просто використовуйте SELECTзапит, як показано нижче.

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

32

Два підходи для вставки з вибором підзапиту.

  1. З підзапитом SELECT повертає результати з одним рядком .
  2. З підзапитом SELECT, що повертає результати з кількома рядками .

1. Підхід до підзапиту SELECT, що повертає результати з одним рядком .

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

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

2. Підхід до підзапиту SELECT, що повертає результати з декількома рядками .

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

Другий підхід буде працювати в обох випадках.


29

Це можна зробити без вказівки стовпців у INSERT INTOчастині, якщо ви надаєте значення для всіх стовпців у SELECTчастині.

Скажімо, таблиця1 має дві колонки. Цей запит повинен працювати:

INSERT INTO table1
SELECT  col1, col2
FROM    table2

Це НЕ БУДЕ працювати (значення для col2не вказано):

INSERT INTO table1
SELECT  col1
FROM    table2

Я використовую MS SQL Server. Я не знаю, як працюють інші RDMS.


24

Це ще один приклад використання значень з select:

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

Стара відповідь і досі корисна. Досить простий і очевидний, але точно відповідає моїм потребам. Дякую!
Себастьян Качмарек

21

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

    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

Масове вставлення, коли потрібно вставити лише потрібний стовпець таблиці (table1):

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

17

Ось ще один приклад, коли джерело береться за допомогою декількох таблиць:

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;

17

Просто використовуйте дужки для пропозиції SELECT в 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'
);

Дякую @Das Його працює для мене ....
Raj G

16

Ось як вставити з декількох таблиць. Цей конкретний приклад, коли у вас є таблиця відображення за сценарієм від багатьох до багатьох:

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, необхідний, коли Id - стовпець Identity і невідомий.)


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

Це працює у всіх СУБД


14

Ви можете спробувати це, якщо ви хочете вставити весь стовпчик за допомогою SELECT * INTOтаблиці.

SELECT  *
INTO    Table2
FROM    Table1;

13

Я фактично віддаю перевагу наступному в 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 (), і ви просто вибираєте, які значення йдуть у таблиці.


13

Це працювало для мене:

insert into table1 select * from table2

Речення дещо відрізняється від виступу Oracle.


12

Для 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 
        }
    }
}
[;]

Це повинно застосовуватися для будь-яких інших наявних там RDBMS. Немає сенсу згадувати весь синтаксис для всіх продуктів IMO.


Я повністю не згоден, я дивився на ці синтаксичні висловлювання роками і досі не можу скласти з них голову чи хвости. Приклади набагато корисніші
reggaeguitar

Це не відповідь, це відповідь "читайте документи", і ось про це
reggaeguitar

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

@ggorlen Мені це здається досить очевидним
reggaeguitar

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

9
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

9

Найкращий спосіб вставити кілька записів з будь-яких інших таблиць.

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)

2

Якщо ви пройдете маршрут 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", і ви закінчуєте писати тривіальну публікацію, коли нарешті з'ясовуєте, що з цим робити.


6
Питання - "вставити в таблицю, використовуючи введення з іншої таблиці ". Як ваша відповідь відповідає на це питання?
Якісний каталізатор

3
Е, не будьте занадто жорсткі до нього. Він відповів на моє запитання, коли я гуляв. @QualityCatalyst
пояс Камерона

1

ЯКЩО ви хочете вставити деякі дані в таблицю, не бажаючи писати ім'я стовпця.

INSERT INTO CUSTOMER_INFO
   (SELECT CUSTOMER_NAME,
           MOBILE_NO,
           ADDRESS
      FROM OWNER_INFO cm
     WHERE ID>100)

Де стоять таблиці:

            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        ||


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.