T-SQL IsNumeric()和Linq-to-SQL

cdo*_*ner 7 t-sql sql-server isnumeric linq-to-sql

我需要从数据库中找到满足某种格式约定的最高值.具体来说,我想找到看起来最高的价值

EU999999('9'是任意数字)

select max(col)将返回类似'EUZ ...'的内容,例如我想要排除的内容.以下查询可以解决问题,但我无法通过Linq-to-SQL生成此问题.似乎没有SQL Server中的isnumeric()函数的转换.

select max(col) from table where col like 'EU%' 
    and 1=isnumeric(replace(col, 'EU', ''))
Run Code Online (Sandbox Code Playgroud)

编写数据库函数,存储过程或其他任何性质的东西都在我的首选解决方案的列表中,因为这个表是我的应用程序的核心,我不能轻易地用其他东西替换表对象.

什么是下一个最佳解决方案?

Rub*_*ben 13

虽然ISNUMERIC缺少,但您总是可以尝试几乎等效的NOT LIKE '%[^0-9]%,即字符串中没有非数字,或者字符串为空或仅由数字组成:

from x in table 
where SqlMethods.Like(x.col, 'EU[0-9]%') // starts with EU and at least one digit
  && !SqlMethods.Like(x.col, '__%[^0-9]%') // and no non-digits
select x;
Run Code Online (Sandbox Code Playgroud)

当然,如果你知道数字的位数是固定的,这可以简化为

from x in table 
where SqlMethods.Like(x.col, 'EU[0-9][0-9][0-9][0-9][0-9][0-9]')
select x;
Run Code Online (Sandbox Code Playgroud)


Ahm*_*eed 11

您可以ISNUMERIC通过向DataContext的分部类添加方法来使用该函数.它类似于使用UDF.

在您的DataContext的部分类中添加以下内容:

partial class MyDataContext
{
    [Function(Name = "ISNUMERIC", IsComposable = true)]
    public int IsNumeric(string input)
    {
        throw new NotImplementedException(); // this won't get called
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你的代码将以这种方式使用它:

var query = dc.TableName
              .Select(p => new { p.Col, ReplacedText = p.Col.Replace("EU", "") })
              .Where(p => SqlMethods.Like(p.Col, "EU%")
                        && dc.IsNumeric(p.ReplacedText) == 1)
              .OrderByDescending(p => p.ReplacedText)
              .First()
              .Col;

Console.WriteLine(query);
Run Code Online (Sandbox Code Playgroud)

或者你可以使用MAX:

var query = dc.TableName
              .Select(p => new { p.Col, ReplacedText = p.Col.Replace("EU", "") })
              .Where(p => SqlMethods.Like(p.Col, "EU%")
                  && dc.IsNumeric(p.ReplacedText) == 1);

var result = query.Where(p => p.ReplacedText == query.Max(p => p.ReplacedText))
                  .First()
                  .Col;

Console.WriteLine("Max: {0}, Result: {1}", max, result);
Run Code Online (Sandbox Code Playgroud)

根据您的最终目标,可以在max变量处停止并在其前面添加"EU"文本,以避免获取列名称的第二个查询.

编辑:正如评论中所提到的,这种方法的缺点是,对文本而不是数值进行排序,并且目前没有针对Int32.ParseSQL的翻译.