2008-09-30 181 views
4

什么表A中插入信息,并使用该指数从表A中的涉及到表B.最好的办法最好的方法,使双插入

的“解决方案”我试图在插入表A的信息(其中有一个自动生成的ID),那么,选择的最后一个索引,并在表B.插入这可能不是非常有用,因为最后一个索引可在插入物之间改变,因为另一个用户可以生成表A

一个新的索引

我有这个问题与各种DBMS postgreSQL,Informix,MySQL和MSSQL(感谢lomaxx的答案)

+0

我认为你的问题可能会更清楚一些,'表A'的索引并不自动意味着“自动生成的值”,这是我认为你所指的。'最后一个索引'在有很多并发时是不可靠的 – 2008-09-30 06:12:17

+0

感谢您的帮助,我会让它更清晰 – seFausto 2008-09-30 06:22:36

+0

有编辑权限的人可以解决这个问题的索引问题吗? – Vidar 2009-01-21 18:04:04

回答

7

如果哟您可以使用MSSQL使用SCOPE_IDENTITY返回当前会话中插入的最后一个ID。然后你可以用它来插入表B.

This article from MSDN给出了一个体面的例子,说明如何做到这一点。

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

另一种选择是创建一个序列,并插入到前表中获取的变量序列值,并用它来插入到两个表。

+0

会不会导致同样的问题? – seFausto 2008-09-30 06:06:36

1

使用IBM Informix Dynamic Server(IDS),它取决于您用于实现双重插入的语言。如果它是服务器(SPL - 存储过程语言),并且如果您使用的是SERIAL列,那么在插入表B时使用DBINFO('sqlca.sqlerrd2')来表示添加到表A的序列值。如果您在客户端(ESQL/C,I4GL,JDBC,ODBC)的工作,则经由接口批准收集串行(sqlca.sqlerrd [1]在ESQL/C,sqlca.sqlerrd [2] I4GL),然后将其传送再次回来。

IDS还支持序列号,以便您可以使用该技术来代替。

IDS 11.50支持SERIAL8和BIGSERIAL以及SERIAL(一个4字节整数);每个细节的接口略有不同,但基本原理是一样的。

0

如果你的表是UUID键控,产生UUID和两个插入使用。

0

Microsoft Knowledge Base中描述了Access 2000+(Jet 4.0)答案。基本上,您可以使用SELECT @@Identity来检索连接上生成的自动增量字段的值。

0

另一接入2000+(喷气4.0)的答案是创建一个Jet 4.0 VIEW(在Access术语:一个SELECT查询保存为查询对象)与上IDENTITY(自动编号)柱的INNER JOIN;连接列必须显示在SELECT子句和引用的表中。然后INSERT INTOVIEW为没有DEFAULT的所有NOT NULL列提供值。

可以省略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) 
; 
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后立刻存储在一个变量,以避免日后的维护代码被损坏的价值。

这也是使用存储过程的最佳实践。

2

在Oracle中,使用序列保持PK值,并用返回的条款

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 /数据操作的appilcation层的最佳实践。

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

Here's the Link

(出于某种原因,在我的工作电脑它描述了在西班牙的一切,也许是因为在墨西哥)

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片段以及