Я пытаюсь INSERT INTO
таблицы, используя ввод из другой таблицы. Хотя это вполне выполнимо для многих движков баз данных, мне всегда трудно вспомнить правильный синтаксис для SQL
движка того времени (MySQL, Oracle, SQL Server, Informix и DB2).
Существует ли синтаксис "серебряной пули" из стандарта SQL (например, SQL-92), который позволил бы мне вставлять значения, не заботясь о базовой базе данных?
Попробуйте:
INSERT INTO table1 ( column1 )
SELECT col1
FROM table2
Это стандартный ANSI SQL и должен работать на любой СУБД
Это определенно работает для:
@Shadow_x99: Это должно работать нормально, и вы также можете иметь несколько столбцов и другие данные:
INSERT INTO table1 ( column1, column2, someInt, someVarChar )
SELECT table2.column1, table2.column2, 8, 'some string etc.'
FROM table2
WHERE table2.ID = 7;
Edit: Я должен упомянуть, что я использовал этот синтаксис только с Access, SQL 2000/2005/Express, MySQL и PostgreSQL, так что они должны быть покрыты. Один из комментаторов указал, что это будет работать с SQLite3.
Чтобы получить только одну стоимость во много стоимости 'ВСТАВЛЯЮТ' от другого стола, я сделал следующее в 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 и, как я ожидаю, во всех СУБД. (Когда-то, 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 ( ... )
и имя владельца в системном каталоге будет "SOMEONE", а не 'someone'. Если заключить имя владельца в двойные кавычки, оно будет действовать как разделенный идентификатор. В стандартном SQL разделенные идентификаторы можно использовать во многих местах. В Informix вы можете использовать их только в именах владельцев - в других контекстах Informix рассматривает строки в одинарных и двойных кавычках как строки, а не разделяет строки в одинарных кавычках как строки, а строки в двойных кавычках как разделительные идентификаторы. (Конечно, для полноты картины существует переменная среды DELIMIDENT, которая может быть установлена - в любое значение, но Y является наиболее безопасным - чтобы указать, что двойные кавычки всегда окружают разграниченные идентификаторы, а одинарные кавычки всегда окружают строки).
Обратите внимание, что MS SQL Server умудряется использовать [разделенные идентификаторы], заключенные в квадратные скобки. На мой взгляд, это выглядит странно и, конечно, не является частью стандарта SQL.
Чтобы добавить что-то в первом ответе, когда мы хотим только немного отчетов от другого стола (в этом примере только один):
INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4)
VALUES (value1, value2,
(SELECT COLUMN_TABLE2
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);
Большинство баз данных следует за основным синтаксисом,
INSERT INTO TABLE_NAME
SELECT COL1, COL2 ...
FROM TABLE_YOU_NEED_TO_TAKE_FROM
;
Каждая база данных, которую я использовал, следует за этим синтаксисом а именно, 'DB2', 'SQL-сервером', 'МОЙ SQL', 'PostgresQL'
Вместо части 'ЦЕННОСТЕЙ' вопроса 'ВСТАВКИ' просто используйте 'ИЗБРАННЫЙ' вопрос как ниже.
INSERT INTO table1 ( column1 , 2, 3... )
SELECT col1, 2, 3... FROM table2
Это может быть сделано, не определяя колонки в 'ВСТАВКЕ В' часть, если Вы поставляете ценности для всех колонок в 'ИЗБРАННОЙ' части.
Let' s говорят, что у table1 есть две колонки. Этот вопрос должен работать:
INSERT INTO table1
SELECT col1, col2
FROM table2
Это НЕ работало бы (стоимость для 'col2' не определена):
INSERT INTO table1
SELECT col1
FROM table2
I' m использование SQL-сервера MS. Я don' t знают, как работают другие RDMS.
Это - другой пример, используя ценности с избранным:
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
Оптовая вставка, когда Вы хотите вставить только в желаемую колонку таблицы (table1):
Insert into Table1 (Column1,Column2 ....Desired Column from Table1)
Select Column1,Column2..desired column from #table2
from #table2
Два подхода для вставки в с избранным подвопросом.
1. Подход для С ИЗБРАННЫМ возвращением подвопроса заканчивается с один row.
INSERT INTO <table_name> (<field1>, <field2>, <field3>)
VALUES ('DUMMY1', (SELECT <field> FROM <table_name> ),'DUMMY2');
В этом случае это предполагает, что ИЗБРАННЫЙ Подвопрос возвращает только один ряд результата на основе того, ГДЕ условие или совокупность SQL функционируют как СУММА, МАКС, В СРЕДНЕМ и т.д. Иначе это бросит ошибку
2. Подход для С ИЗБРАННЫМ возвращением подвопроса заканчивается с несколько rows.
INSERT INTO <table_name> (<field1>, <field2>, <field3>)
SELECT 'DUMMY1', <field>, 'DUMMY2' FROM <table_name>;
Второй подход будет работать на обоих случаи.
Here' s, как вставить от нескольких столов. Этот конкретный пример - то, где у Вас есть стол отображения во многих многим сценарий:
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 - колонка Идентичности и неизвестен.)
Вот другой пример, где источник взят, используя больше чем один стол:
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 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 Table2
FROM Table1;
Для Microsoft SQL Server я рекомендую учиться интерпретировать СИНТАКСИС, обеспеченный на MSDN. С Google it' s легче чем когда-либо, чтобы искать синтаксис.
Для этого конкретного случая попробовать
Google: вставка site:microsoft.com
Первым результатом будет http://msdn.microsoft.com/en-us/library/ms174335.aspx
прокрутите вниз к примеру (" Используя ИЗБРАННОЕ и ВЫПОЛНЯЮТ варианты вставить данные из другого tables"), если Вы находите трудным интерпретировать синтаксис, данный в верхней части страницы.
[ 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.
Я на самом деле предпочитаю следующее в SQL-сервере 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
Это устраняет шаг добавления Вставки () набор, и Вы просто выбираете, какие ценности входят в стол.
select *
into tmp
from orders
Выглядит хорошим, но работает только если tmp doesn' t существует (создает его и заполняется). (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