Why SQL Updates Fail – Five Reasons(为什么SQL SERVER更新失败-五个原因)

本文探讨了SQL更新语句执行后看似未修改任何记录的原因,解析了大小写敏感、空格填充数据、日期时间戳等常见错误,并提供了检查WHERE子句及数据清理的实用技巧。

"The SQL command ran, there's no error message but nothing changed! What's going on? Do you think it's a virus? Maybe there's a bug in .NET!"

The junior programmer was almost in tears when he came to me for help. Proud and confident in his abilities and faced with failure on what should have been an easy task, the poor little fellow's puffed up ego collapsed like a house of cards. I patted him gently on the shoulder and said soothingly, "It's because you're an idiot."

OK, I didn't really say that.

Actually, having an SQL update statement not change any records and not produce an error is expected and desirable behavior:

If you run an update to add a late fee to all outstanding accounts over 2 weeks late and there are no late accounts….the update will succeed, no records will be modified and there will be no error message. This is as it should be.

When an update does not produce an error and no records are modified, it's because the WHERE clause did not locate any records to update. Sometimes this is OK, other times it is a mistake.

Here are three ways this can happen by mistake:

 

Case Sensitivity Misses:

If the collating sequence of the database or column is case sensitive, the text in the column may not match the text in the WHERE clause: Z123 does NOT equal z123. In SQL Server the default is case insensitive.

 

Space Padded Data:

The field type in the database may space pad the data. In SQL Server, if a column type is char(6) or nchar(6) and 'ABC' is saved, what is actually put in the table is 'ABC   ' (note the 3 spaces after ABC). A search for 'ABC' will fail because 'ABC' does not equal 'ABC   '.

 

Dates with Extraneous Times Stamps

DateTime columns have two components (Date and Time…duh). If you are searching a DateTime column either the data or the search criteria may include a timestamp that causes the search to fail:

12-31-2000 12:23:45 AM does not equal 12-31-2000 12:00:00 AM

When storing dates, it is a best practice to truncate the time of DateTime fields so the times are zero (or 12:00:00 AM).

Here is an SQL statement to scrub existing data:

UPDATE MyTable SET MyDate = dateadd(dd, datediff(dd, 0, MyDate), 0)

When searching for records you can set the search criteria to include only the date by using the Date property of the DateTime structure:

    DateTime SearchDate = DateTime.Now.Date;

Note: SQL Server 2008 has new data types of just DATE and TIME.

 

Bonus: Floating Point Numbers:

This is extremely rare but if you have floating point numbers in the data and expect to use an exact WHERE clause to retrieve and update data, good luck. As everyone knows who's taken Numerical Analysis 1001:

1.50000000000 does not equal 1.49999999999

 

Final:

If you are unsure of what is going to be updated in a statement, it is easy to replace the UPDATE with a SELECT and check what is actually being retrieved.

I hope this helps someone.

[Edit]

One more thing that can cause a WHERE clause to fail….

A field containing NULL will not be found if the WHERE clause is looking for an empty string (and vice versa).

下面来自微软文档,使用from语句进行更新注意的情况:

Use caution when specifying the FROM clause to provide the criteria for the update operation. The results of an UPDATE statement are undefined if the statement includes a FROM clause that is not specified in such a way that only one value is available for each column occurrence that is updated, that is if the UPDATE statement is not deterministic. For example, in the UPDATE statement in the following script, both rows in Table1 meet the qualifications of the FROM clause in the UPDATE statement; but it is undefined which row from Table1 is used to update the row in Table2.

大概意思就是:在使用带有from语句的update时,如果from语句中的表的记录不是一对一的关系,而是一对多,或者是多对多,那么对于update来说,没有办法决定使用哪个记录进行更新的,如下例中的table1中有两条记录和table2中的一条记录对应,那么使用table1中的记录更新table2中的记录的最终结果是不确定的(not deterministic)。

USE AdventureWorks2012;  
GO  
IF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL  
    DROP TABLE dbo.Table1;  
GO  
IF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL  
    DROP TABLE dbo.Table2;  
GO  
CREATE TABLE dbo.Table1   
    (ColA int NOT NULL, ColB decimal(10,3) NOT NULL);  
GO  
CREATE TABLE dbo.Table2   
    (ColA int PRIMARY KEY NOT NULL, ColB decimal(10,3) NOT NULL);  
GO  
INSERT INTO dbo.Table1 VALUES(1, 10.0), (1, 20.0);  
INSERT INTO dbo.Table2 VALUES(1, 0.0);  
GO  
UPDATE dbo.Table2   
SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB  
FROM dbo.Table2   
    INNER JOIN dbo.Table1   
    ON (dbo.Table2.ColA = dbo.Table1.ColA);  
GO  
SELECT ColA, ColB   
FROM dbo.Table2;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值