更新時運算符之間的奇怪行為
我必須維護由一些陰暗的顧問(他們提出工作)實施的 FRP(財務資源規劃)軟體,並將數據儲存在 SQL Server 數據庫中。該軟體在早上從文本文件(來自 ERP)載入一些資訊,然後在執行 4 個作業後 3 小時載入。如果我手動執行所有這些過程,我會在第一份工作中得到相同的結果。這就是為什麼我孤立了這個工作。
我檢查了觸發器,但沒有。我已經檢查了程序,並且都屬於使用者可以在軟體中執行的操作。即使每個使用者都註銷(我關閉了服務,所以沒有使用者會登錄),它仍然會發生。
工作編號 1
UPDATE SOME_TABLE SET VALUE_DATE = DATEADD(dd, DATEDIFF(dd,0,GETDATE()),0) WHERE VALUE_DATE < DATEADD(d,0,GETDATE()) AND FLAG BETWEEN '0' AND '1'
這讓我感到困惑,因為
Flag
只能取 3 個值0,1,2
並且是數值。作業前的數據集
+-------+----------+---------------+---------+ | ENT | AMOUNT | VALUE_DATE | FLAG | +-------+----------+---------------+---------+ | AAA | 10000 | 2018-05-22 | 0 | | AAA | 19999 | 2018-05-21 | 1 | | BBB | 1000 | 2017-12-21 | 2 | | BBB | 2000 | 2018-02-21 | 2 | | BBB | 10000 | 2018-05-15 | 0 | | CCC | 15000 | 2018-04-15 | 1 | +-------+----------+---------------+---------+
is作業執行後的DataSet(今天的日期是2018-06-14)
+-------+----------+---------------+---------+ | ENT | AMOUNT | VALUE_DATE | FLAG | +-------+----------+---------------+---------+ | AAA | 10000 | 2018-06-14 | 1 | | AAA | 19999 | 2018-06-14 | 1 | | BBB | 1000 | 2017-12-21 | 2 | | BBB | 2000 | 2018-02-21 | 2 | | BBB | 10000 | 2018-06-14 | 1 | | CCC | 15000 | 2018-06-14 | 1 | +-------+----------+---------------+---------+
執行的第二個作業
UPDATE SOME_TABLE SET FLAG='0' WHERE OTHER_FLAG IN ('COND1', 'COND2'...) AND FLAG='1'
第二份工作後數據集的結果 - 預期
+-------+----------+---------------+---------+ | ENT | AMOUNT | VALUE_DATE | FLAG | +-------+----------+---------------+---------+ | AAA | 10000 | 2018-06-14 | 0 | | AAA | 19999 | 2018-06-14 | 1 | | BBB | 1000 | 2017-12-21 | 2 | | BBB | 2000 | 2018-02-21 | 2 | | BBB | 10000 | 2018-06-14 | 0 | | CCC | 15000 | 2018-06-14 | 1 | +-------+----------+---------------+---------+
此查詢不僅更新
VALUE_DATE
它還FLAG
在1
每個條目上設置。然後第二個作業在隊列中以將FLAG
值設置回0
它更新的位置。我覺得它很複雜而且效率低下。我想更新它,因為它需要大量的時間和人們每月一次來整理數據庫中的資訊。為什麼
FLAG
專欄會更新?改變FLAG BETWEEN '0' and '1'
會有FLAG in ('0','1')
任何糾正效果嗎?或者任何添加“上下文”分隔符都會有所幫助(“”,’’,(),$$ $$,{},ETC)? 我怎樣才能讓第一份工作只更新
Value_date
時間或flag
完全放棄第二份工作?這樣我可以得到預期的表格結果0``1
我確定這不是軟體問題,因為在軟體中執行操作時日期完整性保持得很好。它僅在執行此作業時發生。
您列出的自行執行的 SQL 語句不會更改該
FLAG
列。我已經整理了一個SQLFiddle,它顯示了該語句本身的作用,您會看到它
FLAG
並沒有改變它。這就是為什麼這麼多人認為該過程涉及觸發器或其他語句的原因。
你說過沒有觸發器 on
SOME_TABLE
。如果是這樣,那麼其他一些聲明正在做出改變。查找該語句的最佳方法是使用 SQL Profiler(或擴展事件)來跟踪作業執行時正在執行的內容。如果相關工作觸發了其他一些語句,這應該告訴你那是什麼。如果您搜尋此站點,您將找到有關這些選項的資訊。
如果您需要向自己證明
UPDATE
語句本身是否導致更改為FLAG
,我建議您執行以下操作:在維護視窗期間:
- 開始交易
- 在該事務中執行
UPDATE
語句- 檢查語句的結果
SOME_TABLE
(再次從事務中)- 回滾事務。
如果沒有事務,並且那個 SQL 語句(不是整個工作,只是那個語句)確實改變了 的值
FLAG
,那麼這要麼與 SQL Server 中的錯誤有關(不是不可能,但有點不可能),或者有嚴重錯誤與您的 SQL Server 安裝。或者,當然,確實有一個觸發器 - 根據您所說的,我假設沒有,但這比錯誤或混亂的 SQL Server 實例更有可能解決方案。
這裡
BETWEEN
的問題與編寫 >= 和 <= 相同。如果 test_expression 的值大於或等於 begin_expression 的值且小於或等於 end_expression 的值,則 BETWEEN 返回 TRUE。
所以,對於你的程式碼,到處都是
FLAG != 2
. 您可以通過測試看到這一點。declare @table table (flag tinyint) insert into @table values (0),(1),(2) select * from @table where flag between '0' and '1' --translates to... select * from @table where flag >= 0 and flag <= 1
使用您的數據,您可以看到為什麼第一行被更新,例如……
declare @table table (ent char(3), amount int, value_date date, flag tinyint) insert into @table values ('AAA',10000,'2018-06-14',0) select * from @table where value_date < DATEADD(d,0,GETDATE()) and flag between 0 and 1