2014-03-12 61 views
0

這是我的架構:mysql的觸發器將無法通過LAST_INSERT_ID()來連接

我想有一個插入到「桌面」或「筆記本電腦」插入來自「電腦」自動生成的ID。這樣可行。

我的問題是當我插入到任何一個表中,我不能選擇last_insert_id();

有什麼我做錯了嗎?我試圖將ID一直傳遞給我的應用程序,以便進一步處理。選擇MAX(id)不是一個有效的解決方案。我的SQL連接使得一個INSERT語句,並且觸發不應該打破這種功能......

Use test; 

CREATE TABLE `laptops` (
    `id` int(11) NOT NULL, 
    `name` varchar(45) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=innodb DEFAULT CHARSET=utf8; 

CREATE TABLE `desktops` (
    `id` int(11) NOT NULL, 
    `name` varchar(45) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
) ENGINE=innodb DEFAULT CHARSET=utf8; 

CREATE TABLE `computers` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `type` varchar(45) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=innodb DEFAULT CHARSET=utf8; 

CREATE TRIGGER `laptops_BINS` BEFORE INSERT ON `laptops` FOR EACH ROW 
BEGIN 
    IF (EXISTS(SELECT id FROM laptops WHERE name = NEW.name)) THEN 
    SET NEW.id = NULL; 
    ELSE 
    INSERT INTO computers (type) VALUES ('laptop'); 
    SET NEW.id = LAST_INSERT_ID(); 
    SET NEW.id = LAST_INSERT_ID(NEW.id); 
    END IF; 
END 

CREATE TRIGGER `desktop_BINS` BEFORE INSERT ON `desktops` FOR EACH ROW 
BEGIN 
    IF (EXISTS(SELECT id FROM desktops WHERE name = NEW.name)) THEN 
    SET NEW.id = NULL; 
    ELSE 
    INSERT INTO computers (type) VALUES ('desktop'); 
    SET NEW.id = LAST_INSERT_ID(); 
    SET NEW.id = LAST_INSERT_ID(NEW.id); 
    END IF; 
END 

INSERT INTO laptops (name) VALUES ('laptop1'); 
INSERT INTO laptops (desktop) VALUES ('desktop1'); 
INSERT INTO laptops (name) VALUES ('laptop2'); 
INSERT INTO laptops (desktop) VALUES ('desktop2'); 

SELECT last_insert_id(); 

期待4,實際上它的0

有什麼想法,我怎麼能解決這個觸發?也許有人可以幫我格式化AFTER_INSERT語句來修復last_insert_id?

我試着將這些值設置爲自動遞增,並且在筆記本電腦和臺式機表中唯一,但都不能解決問題。

回答

1

而不是試圖處理'last_insert_id'的'混亂'。我決定改變表格結構,使其成爲一種更常見的格式。 這是將「筆記本電腦」和「桌面」表更改爲具有「auto_increment」鍵。這將'計算機'表更改爲'筆記本電腦'或'桌面'和'計算機類型'的主鍵'computer_id'。

這裏是表格結構和觸發器。

它已經在windows xp上的mysql 5.5.16上測試過。

CREATE TABLE `laptops` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(45) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; 

CREATE TABLE `desktops` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(45) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; 

CREATE TABLE `computers` (
    `computer_id` int(11) NOT NULL, 
    `computer_type` varchar(45) NOT NULL, 
    PRIMARY KEY (`computer_id`,`computer_type`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

DELIMITER $$ 
USE `testmysql`$$ 
DROP TRIGGER /*!50032 IF EXISTS */ `laptop_bins`$$ 

CREATE 
    /*!50017 DEFINER = 'test'@'localhost' */ 
    TRIGGER `laptop_bins` AFTER INSERT ON `laptops` 
    FOR EACH ROW BEGIN 
     INSERT INTO computers (computer_id, computer_type) VALUES (new.id, 'laptop'); 
    END; 
$$ 
DELIMITER ; 

DELIMITER $$ 
USE `testmysql`$$ 
DROP TRIGGER /*!50032 IF EXISTS */ `desktop_bins`$$ 

CREATE 
    /*!50017 DEFINER = 'test'@'localhost' */ 
    TRIGGER `desktop_bins` AFTER INSERT ON `desktops` 
    FOR EACH ROW BEGIN 
     INSERT INTO computers (computer_id, computer_type) VALUES (new.id, 'desktop'); 
    END; 
$$ 
DELIMITER ; 

示例查詢和輸出:

INSERT INTO laptops (NAME) VALUES ('laptop1'); 
INSERT INTO desktops (NAME) VALUES ('desktop1'); 
INSERT INTO laptops (NAME) VALUES ('laptop2'); 
INSERT INTO desktops (NAME) VALUES ('desktop2'); 

Laptops: 
    id name  
------ --------- 
    1 laptop1 
    2 laptop2 

Desktops: 
    id name  
------ ---------- 
    1 desktop1 
    2 desktop2 

Computers: 
computer_id computer_type 
----------- --------------- 
      1 desktop   
      1 laptop   
      2 desktop   
      2 laptop   
+0

這個結構對於我的用例的問題是我試圖在外部表中爲每個id分配一個屬性。計算機ID,例如位置。所以我有一些表,其中computer_id(並且會有數以百萬計)應該是一個整數,以反映哪個是實際的id。把它們放在一個表中可以用聯合來解決,節省了數據庫空間。 SELECT id,'desktop'FROM desktops UNION SELECT id,'laptop'FROM laptops;感謝您的回覆 – user1955162

+0

是的,我確實懷疑您所描述的可能是一種可能的用例。我仍然認爲試圖操縱'last_insert_id'可能會流下眼淚。如果我認爲'laptops.id'是'computers.id'表的'外鍵',邏輯上不是物理上的,我會正確嗎? 'desktop.id'表格是一樣的嗎? –

+0

是的,它們是外鍵。在我的應用程序中,物理上(或示意性地!)。基本上,每臺機器(在這種情況下,我在我的真實使用情況下處理數據區域,計算機是一個類比)可以具有其他非機器類型齒輪通用的屬性(例如位置可以是機器和人)。所以我確實需要多個表來存儲他們的相關數據。我習慣使用Oracle序列,所以在這裏我有點不知所措。我正在開發一個應用程序,在Oracle許可證上花費$$是不太可能的。 – user1955162

0

這更可能的方法來對答案的要求。

我可以根據需要創建代碼。這裏沒有很多代碼。

問題是在其他數據庫中同步維護表,而不做大量的重複工作。

我的建議:

在「計算機的數據庫 - 擁有一個由「插入後」觸發插入並保持相關的關鍵信息的「computers_new」表。包括「未處理」列。

然後我會定期運行腳本,或者在'computers_new'表發生變化時觸發。它會:

1)將'未處理的'細節轉移到另一個數據庫中的'筆記本','桌面'表。

2)將轉移的記錄標記爲已處理。

優點:

大量的小塊工作。 通過使用交易它是可靠的。

缺點。

確保表格同步。

相關問題