突然出现了一个简单查询的 SQL 转换错误

Pet*_*lan 1 sql t-sql sql-server

在一个运行良好多年的系统上 - 就在今天,我注意到一个错误。

脑洞大开的简单

SELECT InvoiceID
FROM t_Invoices
WHERE DocumentNumber = 3841734
Run Code Online (Sandbox Code Playgroud)

现在给出一个错误:

转换 varchar 值“3841730”时转换失败。到数据类型int。

我不知道 3841730 值来自哪里(尽管它可疑地接近 DocumentNumber 值 - 3841734)我只选择 InvoiceID 那么为什么会出现此错误。

该行的所有数据如下:

InvoiceID   DocumentNumber  Date_Created    IsActive    Date_LastOperated   Date_Closed WF_CurrentState WF_PreviousState    WF_CurrentUser  WF_CurrentCredDeptUser  WF_InitialCredDeptUser  WF_PreviousUser WF_WithCreditorsDept    ApprovedAboveLimit  Approved    DocumentSpec    CostCentreID    Date_Due    PaymentInterestComment  PaymentInterestFlag PaymentInterestCommentFreeText  DocumentSpecOriginal
832128  3841734 2021-04-23 08:57:05.000 1   2021-04-23 08:57:05.000 NULL    1   1   15  15  15  15  1   0   0   \\invoicerouting\DocumentStore\2021\04-Apr\UP-20210423-3841734.pdf  1   NULL    NULL    NULL    NULL    NULL
 
Run Code Online (Sandbox Code Playgroud)

谢谢

Gor*_*off 8

这似乎是导致问题的原因:

WHERE DocumentNumber = 3841734
Run Code Online (Sandbox Code Playgroud)

问题是您正在混合类型。在这种情况下,DocumentNumber似乎是一个字符串而不是一个数字。而且,SQL(所有方言)更喜欢数字而不是字符串,因此它尝试将列转换DocumentNumber为字符串。

价值:

3841730.
Run Code Online (Sandbox Code Playgroud)

是列中的一个值。您可能会也可能不会注意到,但它似乎有一个小数点。啊,好难过。

应该修复数据。但与此同时,修复查询!不要混合数据类型:

WHERE DocumentNumber = '3841734'
Run Code Online (Sandbox Code Playgroud)

你能做些什么来修复数据?首先,找到有问题的值:

select DocumentNumber
from t_Invoices
where try_convert(int, DocumentNumber) is null and DocumentNumber is not null;
Run Code Online (Sandbox Code Playgroud)

修复数据后,您可以执行以下两项操作之一:

  1. 如果你决定你真的想要一个字符串,那么添加一个检查约束来只允许数字(或任何允许的)。
  2. 如果您确定该值确实是一个数字,则将类型更改为int-- 或者如果您需要更大的值,则更改为数字。

我会去(2)。(1) 的一个显着特征是前导零是否重要。

  • @PeteWhelan `TRY_CONVERT` 在每个受支持的 SQL Server 版本以及扩展支持版本中都可用。您使用的 SQL Server 版本不受支持吗?如果是这样,您应该在问题中强调这一点,因为除非您明确说明,否则此处的用户将始终假设您正在使用受支持的软件。SQL Server 2008 已经完全不受支持近两年了,所以您早就该升级实例了。如果您使用的是 2012+,那么您的数据库仍处于 100 或更低的兼容性级别;你现在可能也应该增加它了。 (2认同)