2013-01-02 95 views
0

我有一個主表,比如說tbl,它有三列。假設我創建了一個表格,該表格僅顯示關於col1col2的組合的唯一第一條記錄。這種表的SQL定義如下:MySQL:從僞視圖表更新主表

CREATE TABLE pseudo_view AS SELECT col1, col2, col3 FROM tbl GROUP BY col1 col2 

現在我看到的col1col2所有獨特的組合,在這個新表。我更新了這個表格,以便對給定記錄的col3進行更改。我希望通過影響所有重複記錄,將其應用回主表tbl

我知道這是不可能的標準視圖。然而,有沒有辦法創建一個從屬表,當它被更新時,主表將按照select機制的定義進行更新?我希望有一個解決方案,這個僞視圖表可以自由地更新和刪除其記錄,同時也影響父表。

+0

對於初學者'SELECT COL1,COL2,COL3 FROM TBL GROUP BY COL1 col2'是錯誤的('col3'是不確定的),除非'(COL1,COL2)'是一個獨特的密鑰,在這種情況下,GROUP BY無論如何將是不必要的。 – AndreKR

+1

@AndreKR:不幸的是它在MySQL中有效(在默認設置下)。但是你是對的,它確實產生了'col3'的不確定值(而不是「OP」認爲的「第一個」) –

+0

@Mark哪些行應該受新的「僞」表中的變化影響? (順便說一下,我看起來非常真實的桌子)。只有那些(改變)'col3'?他們都(同col1和col2)? –

回答

1

它將與在pseudo_view一些觸發器和TBL

插入,更新工作,TBL「查看」刪除需要進行相應的更新。通常這很容易。唯一困難的部分是當你刪除最後一對col1和col2時。

對於pseudo_table上的更新和刪除,您需要定義在主服務器上應該更改的內容。

在我的例子中,我選擇min(3)作爲函數,所以當一行更新時,同一行(曾經擁有最小col3的那行)更新,並且一個新的(可能是相同的)計算可消費的價值。

當一行被刪除時,tbl中的所有行都需要去,因爲它們本來會在pseudo中給出一行(並且剛被刪除)。

CREATE TABLE tbl (col1 INT, col2 INT, col3 INT); 
INSERT INTO tbl VALUES (1, 1, 1), (1, 1, 2), (2, 2, 3), (2, 2, 4); 

CREATE TABLE pseudo_view 
    AS 
    SELECT 
     col1, 
     col2, 
     MIN(col3) AS col3 
    FROM tbl 
    GROUP BY col1, col2; 

DELIMITER // 

-- update the row that originally was the min() and make sure that the new row in pseudo is the new min() 
CREATE TRIGGER upd_pseudo 
BEFORE UPDATE ON 
    pseudo_view FOR EACH ROW 
    BEGIN 
    UPDATE tbl 
    SET col3 = NEW.col3 
    WHERE col1 = OLD.col1 
      AND col2 = OLD.col2 
      AND col3 = OLD.col3; 

    SET NEW.col3 := (SELECT 
         MIN(col3) 
        FROM tbl 
        WHERE col1 = OLD.col1 
          AND col2 = OLD.col2); 

    END // 

-- delete all rows in tbl that has this col1 and col2 
CREATE TRIGGER del_pseudo 
AFTER DELETE ON 
    pseudo_view FOR EACH ROW 
    BEGIN 
    DELETE FROM tbl 
    WHERE col1 = OLD.col1 AND col2 = OLD.col2; 
    END // 

-- update pseudo to make sure it's still true 
CREATE TRIGGER upd_tbl 
AFTER UPDATE ON 
    tbl FOR EACH ROW 
    BEGIN 
    UPDATE pseudo_view 
    SET col3 = (SELECT 
        min(col3) 
       FROM tbl 
       WHERE col1 = NEW.col1 AND col2 = NEW.col2) 
    WHERE col1 = NEW.col1 AND col2 = NEW.col2; 
    END// 

-- update pseudo to make sure it's still true 
CREATE TRIGGER ins_tbl 
AFTER INSERT ON 
    tbl FOR EACH ROW 
    BEGIN 
    REPLACE pseudo_view 
     VALUES (NEW.col1, NEW.col2, (SELECT 
            min(col3) 
            FROM tbl 
            WHERE col1 = NEW.col1 AND col2 = NEW.col2)); 
    END// 

-- update pseudo to make sure it's still true 
CREATE TRIGGER del_tbl 
AFTER DELETE ON 
    tbl FOR EACH ROW 
    BEGIN 
    -- todo: add special case when the delete row was the last of that col1/col2-pair 
    REPLACE pseudo_view 
     VALUES (NEW.col1, NEW.col2, (SELECT 
            min(col3) 
            FROM tbl 
            WHERE col1 = NEW.col1 AND col2 = NEW.col2)); 
    END// 
+0

此處不幸的情況是,新記錄添加到主表中時,記錄在主表中更新,或記錄從主表中刪除。因此,根據你的建議,我還需要SQL以外的編程觸發器來處理主表上的插入/更新/刪除操作,該表還必須區分pseudo_view表上的觸發器所發送的那些信息。 –

+0

您可以使用MySQL中的觸發器來解決所有這些問題。我會盡快爲你準備一些代碼。 –