我试图从列中获取最大十进制值,然后向其中添加1以获取下一个值。但是,列的值是varchar类型,这意味着我必须进行过滤,以确保它只尝试投射它可以的值,例如' 123,'同时避免像' 123a'
这样的价值观到目前为止我的尝试是:
public class Customer
{
public Customer()
{
customerID = Guid.NewGuid();
}
public Guid customerID { get; set; } = Guid.NewGuid();
}
然而,当我运行它时,如果ID列中存在诸如9和诸如100之类的值,则MAX将优先考虑9而不是100。
我也尝试过:
get()
但是,这会导致将varchar转换为数字时出错,因为我假设它在过滤掉WHERE子句中的非数字ID之前尝试将其转换为小数。我也试图在开始时摆脱额外的演员阵容,但仍然有同样的问题。
感谢您的帮助!
答案 0 :(得分:1)
你缺少的是空字符串。您的条件:我不喜欢'%[^ 0-9]%'在Id为空字符串时为真。这应该有效:
SELECT
(MAX(CAST(Id AS DECIMAL(38,0))) + 1) AS 'New ID'
FROM database
WHERE Id NOT LIKE '%[^0-9]%'
AND Id <> ''
AND (LEN(Id) + 1) < 39
外部CAST是冗余的(MAX将返回与其参数相同的类型)。
PS:在SELECT子句之前计算WHERE子句,因此如果过滤掉WHERE中的无效值,SELECT中的转换将不会失败。
答案 1 :(得分:0)
您应该使用try_convert()
:
SELECT MAX(TRY_CONVERT(DECIMAL(38, 0), id)) + 1 AS [New ID]
FROM database
WHERE Id NOT LIKE '%[^0-9]%' AND (LEN(Id) + 1) < 39 ;
您的示例转换回小数,但我认为您需要一个字符串:
SELECT TRY_CONVERT(VARCHAR(38), MAX(TRY_CONVERT(DECIMAL(38, 0), id)) + 1) AS [New ID]
FROM database
WHERE Id NOT LIKE '%[^0-9]%' AND (LEN(Id) + 1) < 39 ;
您面临的问题是基于SQL Server如何处理查询。我们打算在WHERE
之前处理SELECT
子句。但是,这可能不是计算的设置方式。因此,SQL Server最终会在转换将被过滤掉的值时进行不必要的工作 - 但是在中断查询时会出现错误。
在我看来,这是SQL Server实现中的一个错误。人们假设他们有充分的理由允许错误流过,即使没有选择行。我们都同意这是一个不便之处。
在TRY_CONVERT()
之前,CASE
语句将用于此目的。
答案 2 :(得分:0)
首先转换为十进制,然后获取最大(数字)值(所以10> 9),然后加1,然后在必要时转换为字符串。
Iterator