線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:12931
推到 Plurk!
推到 Facebook!

trigger 問題,寫一個Table update 另一個Table

答題得分者是:herbert2
weiliching
初階會員


發表:53
回覆:78
積分:31
註冊:2003-12-27

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-10-08 14:20:18 IP:42.119.xxx.xxx 訂閱
 ALTER TRIGGER Up_DeclareDate ON M_ARM
AFTER Update
AS
UPDate M_ReceiptD
Where M_ARM.M_ARNo = M_ReceiptD.M_ARNo
Set M_ReceiptD.M_DeclareDate = M_ARM.M_DeclareDate
GO
訊息156,層級15,狀態1,程序Up_DeclareDate,行10
接近關鍵字'Where' 之處的語法不正確。
為何Where 上會有錯誤呢?
herbert2
尊榮會員


發表:58
回覆:640
積分:894
註冊:2004-04-16

發送簡訊給我
#2 引用回覆 回覆 發表時間:2011-10-08 20:39:25 IP:202.39.xxx.xxx 訂閱
是否該這麼寫?!

UPDate M_ReceiptD
Set M_ReceiptD.M_DeclareDate = M_ARM.M_DeclareDate
Where M_ARM.M_ARNo = M_ReceiptD.M_ARNo
GO
weiliching
初階會員


發表:53
回覆:78
積分:31
註冊:2003-12-27

發送簡訊給我
#3 引用回覆 回覆 發表時間:2011-10-09 10:35:28 IP:113.161.xxx.xxx 訂閱
 你好,是自己忽然沒看清處寫法,更改後.發生錯誤
訊息 4104,層級 16,狀態 1,程序 Up_DeclareDate,行 7
無法繫結多重部分 (Multi-Part) 識別碼 "M_ARM.M_ARNo"。
herbert2
尊榮會員


發表:58
回覆:640
積分:894
註冊:2004-04-16

發送簡訊給我
#4 引用回覆 回覆 發表時間:2011-10-09 20:37:14 IP:202.39.xxx.xxx 訂閱
Sorry! 只看到您 WHERE 寫錯位置, 沒多想故漏注意您的 Set = 的寫法也錯了.

因不熟悉 MS-SQL 語法細節, 僅以 SQL-92 標準寫法試改如下:

UPDate M_ReceiptD
Set M_ReceiptD.M_DeclareDate = (SELECT M_ARM.M_DeclareDate FROM M_ARM
Where M_ReceiptD.M_ARNo = M_ARM.M_ARNo);
UPDate M_ReceiptD A
Set A.M_DeclareDate = (SELECT B.M_DeclareDate FROM M_ARM B
Where A..M_ARNo = B.M_ARNo);

延伸, UPDATE 多個 Column:
UPDATE Table1 A
SET (A.Column1,A.Column2,A.Column3,......) = (SELECT B.Col1,B.Col2,B.Col3,...... FROM Tabel2 B
WHERE A.Key1 = B.Key1 AND A.key2 = B.Key2 ......);
weiliching
初階會員


發表:53
回覆:78
積分:31
註冊:2003-12-27

發送簡訊給我
#5 引用回覆 回覆 發表時間:2011-10-10 12:08:56 IP:42.119.xxx.xxx 訂閱
 我也更改了,但是在delphi 發生一個錯誤, 就是 

"索引鍵資料行資料訊息不足, 太多資料列被更新所影響,"

其實我只要更改一筆,他能相對的更改那Table 的某欄位,
但是我這程式寫法好像是全部都會更新.
herbert2
尊榮會員


發表:58
回覆:640
積分:894
註冊:2004-04-16

發送簡訊給我
#6 引用回覆 回覆 發表時間:2011-10-10 14:43:14 IP:202.39.xxx.xxx 訂閱
因您未言明目的, 故依您語法猜測而答.
上回所寫的 SQL 確實是更新整個 M_ReceiptD 檔.
若您只是要更新一筆, 則絕對不可用 DOS DBase III 的想法去寫,
因在 Data Base 中, 並不像 DBase III 那樣, M_ReceiptD.M_ARNo 是目前 M_ReceiptD 檔所在那筆的 M_ARNo
(根本沒有目前所在那筆), 而是整個 M_ReceiptD 檔全部 Rows 的 M_ARNo.

在 M_ARM 檔的 Trigger 要更新 M_ReceiptD 檔中的一筆的寫法為:
UPDate M_ReceiptD
Set M_DeclareDate = :New.M_DeclareDate
Where M_ARNo = :New.M_ARNo;
(:New.M_DeclareDate 與 :New. M_ARNo 為 M_ARM 檔剛 Update 那 Row 的新欄值,
若 M_ReceiptD.M_ARNo 非 Unique, 則可能會更新 M_ReceiptD 檔中的多筆)

編輯記錄
herbert2 重新編輯於 2011-10-10 00:56:20, 註解 無‧
herbert2 重新編輯於 2011-10-10 00:57:14, 註解 無‧
herbert2 重新編輯於 2011-10-10 00:58:38, 註解 無‧
herbert2 重新編輯於 2011-10-10 06:49:29, 註解 無‧
weiliching
初階會員


發表:53
回覆:78
積分:31
註冊:2003-12-27

發送簡訊給我
#7 引用回覆 回覆 發表時間:2011-10-12 08:36:46 IP:42.119.xxx.xxx 訂閱
M_ReceiptD.M_ARNo 是非 Unique ,目的也是要同時更新,
但是還是有以下錯誤,
訊息 102,層級 15,狀態 1,程序 Up_DeclareDate,行 7
接近 ':' 之處的語法不正確。的錯誤.
但我試這更改,把:拿掉,或是加上Table ,但是一樣還是有同樣問題.
herbert2
尊榮會員


發表:58
回覆:640
積分:894
註冊:2004-04-16

發送簡訊給我
#8 引用回覆 回覆 發表時間:2011-10-12 16:17:56 IP:202.39.xxx.xxx 訂閱
今初閱 MS-SQL 有關 Trigger 的簡介, 發現它與 Oracle 很不同.

Oracle Update 時, 產生 :Old 與 :New 兩個與 Table 同結構的 Cursor,
Trigger 有 FOR EACH ROW 的語法使 Trigger 針對每一筆資料做反應.
MS-SQL 則產生 DELETED 與 INSERED 兩個與 Table 同結構的系統臨時 Table.
Trigger 無 FOR EACH ROW 的語法限制 Trigger 針對每一筆資料做反應,
是自動針對每一筆資料做反應嗎? 我尚不確定.

Oracle 有 SELECT ColName INTO Variable FROM Table WHERE .... 語法,
MS-SQL 則為 SELECT ColName INTO Table2 FROM Table1 WHERE .... (或許我沒看到較完整的資訊?)
或 SELECT @Variable = ColName FROM Table WHERE ....

Oracle 以『;』做為一個 Statement 的結束,
MS-SQL 則由 Compiler 自動判定, 一句 Statement 可有多 Rows, 與另一句 Statement 只須換 Row 即可.

故, 這個 Trigger 似乎該寫成:
UPDATE M_ReceiptD
SET M_DeclareDate = (SELECT M_DeclareDate FROM INSERTED)
WHERE M_ARNo = (SELECT M_ARNo FROM INSERTED)
GO

或使用變數:
DECLARE @NewDate CHAR(20), @NewNo CHAR(20)
SELECT @NewDate = M_DeclareDate FROM INSERTED
SELECT @NewNo = M_ARNo FROM INSERTED
UPDate M_ReceiptD
Set M_DeclareDate = @NewDate
WHERE M_ARNo = @NewNo
GO

但您這 Trigger 有個問題, 若一次 UPDATE 多筆 M_ARM, 且 MS-SQL 之該 Trigger
並非針對每一筆資料做反應, 那就不能寫得這麼陽春了.
因 Trigger 不是只針對您前端的 AP 做反應, 直接從資料庫下 UPDATE 指令它也一樣被觸發,
故或許改使用 Stored Procedure 處理會比用 Trigger 處理較安全、方便.

還有, M_ARM.M_ARNo 不會被修改嗎? 否則應該也要考慮吧?!
編輯記錄
herbert2 重新編輯於 2011-10-12 02:24:47, 註解 無‧
weiliching
初階會員


發表:53
回覆:78
積分:31
註冊:2003-12-27

發送簡訊給我
#9 引用回覆 回覆 發表時間:2011-10-14 11:03:01 IP:113.161.xxx.xxx 訂閱
已解決~程式我已改寫成, 謝謝指導~

declare
@new_M_DeclareDate datetime,
@old_M_ARNo varchar(20)
set @new_M_DeclareDate=(select M_DeclareDate from inserted)
set @old_M_ARNo=(select M_ARNo from deleted)
IF UPDATE(M_DeclareDate)
begin
UPDate M_ReceiptD
Set M_ReceiptD.M_DeclareDate = @new_M_DeclareDate
Where M_ReceiptD.M_ARNo=@old_M_ARNo
end
Go
系統時間:2024-11-21 17:07:36
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!