2008-09-30 48 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片段以及