选择最大varchar转换为小数

时间:2016-05-10 20:49:44

标签: sql sql-server sql-server-2012

我试图从列中获取最大十进制值,然后向其中添加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之前尝试将其转换为小数。我也试图在开始时摆脱额外的演员阵容,但仍然有同样的问题。

感谢您的帮助!

3 个答案:

答案 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