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


Пытаться:
INSERT INTO table1 ( column1 )
SELECT col1
FROM table2
Это стандартный ANSI SQL, который должен работать в любой СУБД.
Это определенно работает для:
Ответ Клода Уля: должно работать нормально, и вы также можете иметь несколько столбцов и другие данные:
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/…
Проблем со вставкой более одной строки быть не должно.
Обязательно ли вставлять во все столбцы таблицы
@maheshmnj нет, только столбцы, для которых установлено значение NOT NULL, и не нужно включать значение по умолчанию, для любых других столбцов будут установлены значения по умолчанию или NULL
Оба ответа, которые я вижу, отлично работают в 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.
Я полностью не согласен, я годами изучал эти синтаксические утверждения и до сих пор не могу понять их. Примеры намного полезнее
Это не ответ, он говорит «прочтите документацию», и это все.
На самом деле я предпочитаю в 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, но не оба одновременно.
Это правда, что в документации это не указано, но это работает. Тем не менее, я думаю, что использование оператора select вместо значений делает его более читабельным.
Он работает для указания значения внутри строки, но в более общем случае требуется получить много строк.
Если val_1 не изменяется по строкам, то следующий синтаксис может работать в SQLite3? выберите 'foo', some_column из some_table - работает в SQLServer 2014
В документации это перечислено (сейчас?): Этот синтаксис - INSERT INTO ... VALUES ([expr], [expr], ...), а один из путей в [expr] - {{NOT} EXISTS} ([select-stmt]) - обратите внимание, что скобки вокруг оператора select обязательны ({} означает необязательный)
что, если выбор вернет более 1 строки?
@Lee Это отличный вопрос. Я думаю, что когда я работал с этим val2, возможно, он был ПК или какой-то другой уникальной областью, поэтому он никогда не появлялся.
Простая вставка, если известна последовательность столбцов таблицы:
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 ...
Старый ответ и все еще полезный. Довольно просто и очевидно, но полностью удовлетворяет мои потребности. Спасибо!
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.
Вместо части 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», и вы в конечном итоге напишете тривиальный пост, когда наконец выясните, что с этим делать.
Вопрос в том, «вставить в таблицу по входу из другого стола». Как ваш ответ отвечает на этот вопрос?
Эх, не будь с ним слишком суров. Он ответил на мой вопрос, когда я искал в Google. @QualityCatalyst
INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT COLUMN_NAME
FROM ANOTHER_TABLE_NAME
WHERE CONDITION;
@ggorlen Мне это кажется самоочевидным
Он был помечен в очереди на проверку как ответ, содержащий только код. Однако я могу понять вашу точку зрения - теперь, когда я вижу это в естественной среде, в контексте большинства ответов на этой странице особо нечего сказать.
Лучший способ вставить несколько записей из любых других таблиц.
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. Подход для подзапроса 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 ||
этот пример работает: вставить в tag_zone select @ tag, zoneid, GETDATE (), @ positiong.STIntersects (polygon) from zone