Вопрос

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

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

Это было полезно?

Решение

Пытаться:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

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

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

  • Оракул
  • MS SQL-сервер
  • MySQL
  • Постгрес
  • SQLite v3
  • Терадата
  • DB2
  • Сибаза
  • Вертика
  • HSQLDB
  • Н2
  • AWS RedShift
  • SAP Хана

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

@Тень_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.

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

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

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

прекрасно работает с Informix и, как я ожидал, со всеми СУБД.(Давным-давно, пять или более лет назад 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 TABLE_NAME
SELECT COL1, COL2 ...
FROM TABLE_YOU_NEED_TO_TAKE_FROM
;

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

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

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

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

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

INSERT INTO table1
SELECT  col1, col2
FROM    table2

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

INSERT INTO table1
SELECT  col1
FROM    table2

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

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

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

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

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

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

    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

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

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 StudentCourseMap (StudentId, CourseId) 
SELECT  Student.Id, Course.Id FROM Student, Course 
WHERE Student.Name = 'Paddy Murphy' AND Course.Name = 'Basket weaving for beginners'

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

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

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

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

SELECT  *
INTO    Table2
FROM    Table1;

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

insert into table1 select * from table2

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

Для Microsoft SQL Server я рекомендую научиться интерпретировать СИНТАКСИС, представленный в 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 нет смысла запоминать весь синтаксис для всех продуктов.

На самом деле я предпочитаю в 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.Например вот так:

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'
);
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 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 INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT  COLUMN_NAME
FROM    ANOTHER_TABLE_NAME 
WHERE CONDITION;

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top