在表A中插入信息并使用表A中的索引与表B相关的最佳方法是什么。
我试过的“解决方案”是在表A中插入信息(它有一个自动生成的ID),然后,选择最后一个索引并将其插入表B.这可能不是很有用,因为最后一个索引可能插入之间的更改,因为另一个用户可以在表A中生成新索引
我遇到过各种DBMS postgreSQL,Informix,MySQL和MSSQL的问题(感谢lomaxx的回答)
答案 0 :(得分:7)
如果您使用的是MSSQL,则可以使用SCOPE_IDENTITY返回当前会话中插入的最后一个ID。然后,您可以使用它插入表B。
This article from MSDN就如何做到这一点提供了一个很好的例子。
答案 1 :(得分:3)
这是序列解决方案(对于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,如果您为多个插页使用相同的连接,则交易非常重要,不要自行绊倒。
对于LAST_INSERT_ID(),最多 最近生成的ID保留在 服务器基于每个连接。 它不会被其他客户更改。 如果你更新,它甚至没有改变 另一个带有的AUTO_INCREMENT列 非魔术值(即一个值 不是NULL而不是0)。运用 LAST_INSERT_ID()和AUTO_INCREMENT 同时从多个列 客户完全有效。每 客户端将收到最后插入的 客户端的最后一个语句的ID 执行。
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)
答案 2 :(得分:2)
另一个选项是创建一个序列,在插入表之前获取变量中的序列值,并使用它来插入两个表。
答案 3 :(得分:2)
在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中使用PACKAGES来存储appilcation的所有SQL / Data操作层。
答案 4 :(得分:1)
使用IBM Informix Dynamic Server(IDS),它取决于您用于实现双插入的语言。如果它是服务器(SPL - 存储过程语言),并且如果您使用SERIAL列,则使用DBINFO('sqlca.sqlerrd2')表示插入表B时添加到表A的序列值。如果您您正在客户端(ESQL / C,I4GL,JDBC,ODBC)工作,您通过批准的接口(ESQL / C中的sqlca.sqlerrd [1],I4GL中的sqlca.sqlerrd [2])收集串行,然后传输它再回来。
IDS也支持序列,因此您可以使用该技术。
IDS 11.50支持SERIAL8和BIGSERIAL以及SERIAL(4字节整数);每个细节界面略有不同,但基本原理是相同的。
答案 5 :(得分:0)
如果您的表是UUID键,请生成UUID并在两个插入中使用它。
答案 6 :(得分:0)
Microsoft Knowledge Base中描述了Access 2000+(Jet 4.0)的答案。基本上,您可以使用SELECT @@Identity
来检索在连接上生成的自动增量字段的值。
答案 7 :(得分:0)
另一个Access 2000+(Jet 4.0)的答案是创建一个Jet 4.0 VIEW
(在Access术语中:保存为Query对象的SELECT
查询),其中包含INNER JOIN
IDENTITY
(自动编号)列;必须在SELECT子句和引用的表中公开连接列。然后INSERT INTO
VIEW
提供没有NOT NULL
的所有DEFAULT
列的值。
IDENTITY
列值可以省略,在这种情况下,引擎将像往常一样自动生成值,或者提供和尊重显式值;如果另外提供了另一个表(没有IDENTITY
列的那个)中的连接列的值,则它必须与IDENTITY
值相同,否则将发生错误;如果省略IDENTITY
值,则将忽略为连接列提供的任何值。请注意,这些表之间通常需要FOREIGN KEY
,但这不是此过程工作的先决条件。
快速示例(ANSI-92查询模式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)
;
答案 8 :(得分:0)
如果您使用的是sql server 2005+,您还可以使用OUTPUT子句输出已更新,插入或删除的数据。它非常酷,而且非常适合您需要它的类型。 http://msdn.microsoft.com/en-us/library/ms177564.aspx
答案 9 :(得分:0)
在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
值存储在变量中,以避免将来的维护代码损坏该值。
使用存储过程也是最佳做法。
答案 10 :(得分:0)
如果它在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);
(出于某种原因,在我的工作计算机中它用西班牙语描述了一切,也许是因为在墨西哥)
答案 11 :(得分:0)
使用事务来避免这个问题:“这可能不是很有用,因为最后一个索引可能会在插入之间发生变化,因为另一个用户可能会在表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片段,请告诉我。