Sql-Server

更新時運算符之間的奇怪行為

  • June 18, 2018

我必須維護由一些陰暗的顧問(他們提出工作)實施的 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它還FLAG1每個條目上設置。然後第二個作業在隊列中以將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 &gt;= 0 
 and flag &lt;= 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 &lt; DATEADD(d,0,GETDATE()) and flag between 0 and 1

引用自:https://dba.stackexchange.com/questions/209605