Как лучше всего вставить информацию в таблицу A и использовать индекс из таблицы A для связи с таблицей B.
«Решение», которое я пробовал, - это вставить информацию в таблицу A (которая имеет автоматически сгенерированный идентификатор), затем выбрать последний индекс и вставить его в таблицу B. Это может быть не очень полезно, поскольку последний индекс может меняться между вставляет, потому что другой пользователь может создать новый индекс в таблице A
У меня была эта проблема с различными СУБД postgreSQL, Informix, MySQL и MSSQL (спасибо lomaxx за ответ)


если вы используете MSSQL, вы можете использовать SCOPE_IDENTITY для возврата последнего идентификатора, вставленного в текущий сеанс. Затем вы можете использовать это для вставки в таблицу B.
Эта статья из MSDN дает достойный пример того, как это сделать.
Это решение последовательности (для postgres), вам, конечно, придется делать это в хранимой процедуре или в коде вашего приложения.
postgres=# create table foo(id serial primary key, text varchar);
NOTICE: CREATE TABLE will create implicit sequence "foo_id_seq" for serial column "foo.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
CREATE TABLE
postgres=# create table bar(id int references foo, text varchar);
CREATE TABLE
postgres=# select nextval('foo_id_seq');
nextval
---------
1
(1 row)
postgres=# insert into foo values (1,'a'); insert into bar values(1,'b');
INSERT 0 1
INSERT 0 1
Для MySQL транзакция важна, чтобы не споткнуться о вас, если вы используете одно и то же соединение для нескольких вставок.
For LAST_INSERT_ID(), the most recently generated ID is maintained in the server on a per-connection basis. It is not changed by another client. It is not even changed if you update another AUTO_INCREMENT column with a non-magic value (that is, a value that is not NULL and not 0). Using LAST_INSERT_ID() and AUTO_INCREMENT columns simultaneously from multiple clients is perfectly valid. Each client will receive the last inserted ID for the last statement that client executed.
mysql> create table foo(id int primary key auto_increment, text varchar(10)) Engine=InnoDB;
Query OK, 0 rows affected (0.06 sec)
mysql> create table bar(id int references foo, text varchar(10)) Engine=InnoDB;
Query OK, 0 rows affected (0.01 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into foo(text) values ('x');
Query OK, 1 row affected (0.00 sec)
mysql> insert into bar values (last_insert_id(),'y');
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.04 sec)
Другой вариант - создать последовательность и перед вставкой в таблицу получить значение последовательности в переменной и использовать его для вставки в обе таблицы.
Разве это не вызовет ту же проблему?
Может быть, не смог полностью оценить ваш вопрос. Если мы присвоим значение локальной переменной, мы узнаем значение. Не уверен, что насчет двух вставок, будут ли они в одном месте или по отдельности. Если вы выполняете массовые вставки в таблице A, а затем в таблице B, то с этим будет сложнее справиться.
В IBM Informix Dynamic Server (IDS) это зависит от языка, который вы используете для реализации двойной вставки. Если это сервер (SPL - язык хранимых процедур), и если вы используете столбец SERIAL, то вы используете DBINFO ('sqlca.sqlerrd2') для представления последовательного значения, добавляемого в Таблицу A при вставке в Таблицу B. работают в клиенте (ESQL / C, I4GL, JDBC, ODBC), вы собираете серийный номер через утвержденный интерфейс (sqlca.sqlerrd [1] в ESQL / C, sqlca.sqlerrd [2] в I4GL), а затем передаете его снова.
IDS также поддерживает последовательности, поэтому вы можете использовать эту технику.
IDS 11.50 поддерживает SERIAL8 и BIGSERIAL, а также SERIAL (4-байтовое целое число); подробные интерфейсы для каждого из них немного отличаются, но основной принцип остается тем же.
Я использую JDBC, как мне собрать серийный номер?
Если ваши таблицы имеют UUID-ключ, сгенерируйте UUID и используйте его в обеих вставках.
Ответ Access 2000+ (Jet 4.0) описан в База знаний Майкрософт. По сути, вы можете использовать SELECT @@Identity для получения значения поля автоинкремента, которое создается в вашем соединении.
Другой ответ Access 2000+ (Jet 4.0) - создать Jet 4.0 VIEW (в терминах Access: запрос SELECT, сохраненный как объект запроса) с INNER JOIN в столбце IDENTITY (Autonumber); соединяемые столбцы должны быть представлены в предложении SELECT и в указанной таблице. Затем INSERT INTO, VIEW, предоставляющий значения для всех столбцов NOT NULL, в которых нет DEFAULT.
Значение столбца IDENTITY может быть либо опущено, и в этом случае механизм будет автоматически генерировать значение, как обычно, либо явное значение, предоставленное и обработанное; если значение объединяющего столбца в другой таблице (той, что без столбца IDENTITY) предоставляется дополнительно, то оно должно быть таким же, как значение IDENTITY, в противном случае возникнет ошибка; если значение IDENTITY опущено, то любое значение, предоставленное для присоединяемого столбца, будет проигнорировано. Обратите внимание, что между такими таблицами обычно ожидается наличие FOREIGN KEY, но это не является предварительным условием для работы этого процесса.
Быстрый пример (синтаксис ANSI-92 Query Mode Jet 4.0):
CREATE TABLE Table1
(
key_col INTEGER IDENTITY NOT NULL PRIMARY KEY,
data_col_1 INTEGER NOT NULL
)
;
CREATE TABLE Table2
(
key_col INTEGER NOT NULL,
data_col_2 INTEGER NOT NULL,
PRIMARY KEY (key_col, data_col_2)
)
;
CREATE VIEW View1
AS
SELECT T1.key_col AS key_col_1, T2.key_col AS key_col_2,
T1.data_col_1, T2.data_col_2
FROM Table2 AS T2
INNER JOIN Table1 AS T1
ON T1.key_col = T2.key_col
;
INSERT INTO View1 (data_col_1, data_col_2)
VALUES (1, 2)
;
если вы используете sql server 2005+, вы также можете использовать предложение OUTPUT, которое выводит данные, которые были обновлены, вставлены или удалены. Это довольно круто и именно для того, для чего вам нужно. http://msdn.microsoft.com/en-us/library/ms177564.aspx
В SQL Server вы используете поле @@ IDENTITY, а также заключаете INSERT в транзакцию.
DEFINE ... etc etc
BEGIN TRANSACTION
INSERT INTO table1 ( value1 ) VALUES ( @p_value1 )
SET @pk_table1 = @@IDENTITY
INSERT INTO table2 ( pk_table1, value2 ) VALUES ( @pk_table1, @p_value2 )
COMMIT
В TSQL лучше всего хранить значение @@IDENTITY в переменной сразу после INSERT, чтобы избежать повреждения значения будущим кодом обслуживания.
Также рекомендуется использовать хранимые процедуры.
В ORACLE используйте последовательности для хранения значений PK и предложение RETURNING.
INSERT INTO table1 ( pk_table1, value1 )
VALUES ( table1_seq.NEXTVAL, p_value1 ) RETURNING pk_table1 INTO l_table1_id;
INSERT INTO table2 ( pk_table2, pk_table1, value2 )
VALUES ( table2_seq.NEXTVAL, l_table1_id, p_value2 );
Лучше всего использовать ПАКЕТЫ в Oracle для хранения всего уровня обработки SQL / данных приложения.
Если это в Informix и JSP, есть функция, которая возвращает поле Serial таблицы после вставки.
import com.informix.jdbc.*;
cmd = "insert into serialTable(i) values (100)";
stmt.executeUpdate(cmd);
System.out.println(cmd+"...okay");
int serialValue = ((IfmxStatement)stmt).getSerial();
System.out.println("serial value: " + serialValue);
(Почему-то на моем рабочем компьютере все описывается на испанском, может быть, потому, что в Мексике)
Используйте транзакцию, чтобы избежать этой проблемы: «Это может быть не очень полезно, поскольку последний индекс может измениться между вставками, потому что другой пользователь может создать новый индекс в таблице A.»
А в PostgreSQL вы можете использовать nextval и currval для выполнения того, что хотите:
BEGIN;
INSERT INTO products (prod_id, prod_name, description) VALUES (
nextval('products_prod_id_seq')
, 'a product'
, 'a product description'
);
INSERT INTO prices (price_id, prod_id, price) VALUES (
nextval('prices_price_id_seq')
, currval('products_prod_id_seq')
, 0.99
);
COMMIT;
Сообщите мне, если вам также понадобится фрагмент DDL.
Думаю, ваш вопрос мог бы быть яснее. «Индекс из таблицы A» не означает автоматически «автоматически сгенерированное значение», о чем, я думаю, вы имеете в виду. «Последний индекс» ненадежен, когда одновременно работает много пользователей.