Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
筛选出的字符串仍会导致SQL语句出错_Sql_Sql Server 2008 R2 - Fatal编程技术网

筛选出的字符串仍会导致SQL语句出错

筛选出的字符串仍会导致SQL语句出错,sql,sql-server-2008-r2,Sql,Sql Server 2008 R2,我正在使用SQLServer2008R2 我正在编写一个零件号生成器应用程序。我们的零件号由9位数字组成,如914602001。在创建新编号之前,如果已经存在,则需要检查多个来源。为了节省时间,我创建了一个简单的源代码联合。工会成员如下: SELECT DISTINCT ItemNumber FROM dbo.EngPartNumbers WHERE (ItemNumber NOT LIKE '%[^0-9]%') UNION SELECT DISTINCT ValueText COLLATE

我正在使用SQLServer2008R2

我正在编写一个零件号生成器应用程序。我们的零件号由9位数字组成,如914602001。在创建新编号之前,如果已经存在,则需要检查多个来源。为了节省时间,我创建了一个简单的源代码联合。工会成员如下:

SELECT DISTINCT ItemNumber
FROM dbo.EngPartNumbers
WHERE (ItemNumber NOT LIKE '%[^0-9]%')
UNION
SELECT DISTINCT ValueText COLLATE SQL_Latin1_General_CP1_CI_AS AS ItemNumber
FROM [PDMWE-Bel-ArtProductsDocManagement].dbo.VariableValue AS vv
WHERE (ValueText NOT LIKE '%[^0-9]%') AND (LEN(ValueText) = 9)
第一个表EngPartNumbers是导入到SQL中的Excel文件。它包含一列ItemNumber,并且是varchar数据类型。它必须是varchar,因为我们在命名约定中使用了字母

第二个表是我们的EPDM,其中VariableValue是存储所有变量值的表,它位于variables表中。ValueText列是保存所有变量值的varchar。在我的例子中,我只关心9位数字值,所以我应用了最后一行:

WHERE (ValueText NOT LIKE '%[^0-9]%') AND (LEN(ValueText) = 9) 
工会的结果是我所期望的;仅限数字:

这就是我的问题所在。因为我想得到下一个可用的数字,所以我想使用int数据类型,而不是varchar。当我从视图中选择所有内容时,将列强制转换为int,并添加WHERE子句,如下所示:

SELECT ItemNumber 
FROM (
    SELECT CAST(ItemNumber AS int) AS ItemNumber 
    FROM vw_PDM_Union_Items
    ) AS x
WHERE ItemNumber < 800900000
SELECT CAST(ItemNumber AS int) AS ItemNumber
FROM (SELECT DISTINCT ItemNumber
      FROM dbo.EngPartNumbers
      WHERE (ItemNumber NOT LIKE '%[^0-9]%')
      UNION
      SELECT DISTINCT ValueText 
          COLLATE SQL_Latin1_General_CP1_CI_AS AS ItemNumber
      FROM [PDMWE-Bel-ArtProductsDocManagement].dbo.VariableValue AS vv
      WHERE (ValueText NOT LIKE '%[^0-9]%') 
          AND (LEN(ValueText) = 9)) AS item
WHERE     (ItemNumber NOT LIKE '%[^0-9]%')
但我还是犯了同样的错误。SQL为什么会这样做?背景中发生了什么导致它查看原始表?如果有人能说明这种情况,并给我一个更好的方法来完成这一点,将不胜感激。为了便于操作,我希望使用int列,而不是varchar

提前感谢。

使用bigint或decimal:

我还注意到子查询中有一个长度限制。由于SQL Server的工作方式,在尝试转换值后可能会调用此函数

您可以使用case强制执行求值顺序:


我可能建议您实际将此逻辑移到视图中。

现在已复制了它

select * 
from (
    SELECT CAST(valuetext AS int)  AS ItemNumber
    FROM (
          select valuetext='SW-Revision' 
          union 
          select '123456789'
         ) AS vv
    WHERE (ValueText NOT LIKE '%[^0-9]%') 
) wrapper
where ItemNumber > 0;
我猜这是由于谓词推送。作为解决办法

SELECT * 
FROM (
    SELECT CAST(CASE WHEN valuetext NOT LIKE '%[^0-9]%' THEN valuetext END AS int)  AS ItemNumber
    FROM (
          select valuetext='SW-Revision' 
          union 
          select '123456789'
         ) AS vv
    WHERE (ValueText NOT LIKE '%[^0-9]%') 
) wrapper
WHERE ItemNumber > 0

您可以很容易地重新创建此错误

SELECT  *
FROM    (   SELECT  ValueText
            FROM    (VALUES ('A'), ('1')) t (ValueText)
            WHERE   t.ValueText NOT LIKE '%[^0-9]%'
        ) t
WHERE   ValueText < 10;
给出了以下执行计划:

您可以看到,SQL Server有效地简化了查询,直至:

SELECT  ValueText
FROM    (VALUES ('A'), ('1')) t (ValueText)
WHERE   TRY_CONVERT(INT, ValueText) < 10;
AND     t.ValueText NOT LIKE '%[^0-9]%';
这是一种黑客行为,虽然在大多数情况下我不得不使用它,但不能保证它能正常工作,但是使用TOP和一个比您需要的大得多的数字通常会强制中间实现结果

三,。使用大小写表达式删除记录


同样,这是可行的,但我看不出它能保证有效,未来的更新没有理由不承认where谓词和case谓词是相同的,并优化case表达式。

我很好奇这是否有效

SELECT ItemNumber 
FROM (
    SELECT case isnumeric(ItemNumber) 
        when 1 then CAST(ItemNumber AS int) 
        else -999999999
        end
        AS ItemNumber
    FROM vw_PDM_Union_Items
) AS x
WHERE ItemNumber < 800900000 
    and ItemNumber>-999999999

我尝试了一些不同的想法,使用了bigint和decimal,包括您的示例,但仍然出现了以下错误:将nvarchar转换为数据类型numeric时出现算术溢出错误。@GunnarHerman。SQL Server在优化查询时会重新排列查询,因此可能会在筛选之前转换为数值。Microsoft认为这是一项功能,因为它支持某些优化。查看我的答案上的编辑。基本上你在那里创建的是我的视图,它只返回数字并过滤掉字符串,这很好。如果将其包装在select语句中并添加“WHERE ItemNumber<99999999”,则会出现错误。这就是我面临的问题。如果您案例中的view或嵌套SQL语句过滤掉了所有字母数字行,为什么会出现错误?我可以使用方法1并向其中添加一些行以获得所需的内容。这将非常有效,我感谢你详细解释一切。其他人,我感谢你们的回复和帮助我解决这个问题的努力。非常感谢。
SELECT  *
FROM    (   SELECT  ValueText
            FROM    (VALUES ('A'), ('1')) t (ValueText)
            WHERE   t.ValueText NOT LIKE '%[^0-9]%'
        ) t
WHERE   ValueText < 10;
SELECT  *
FROM    (   SELECT  ValueText
            FROM    (VALUES ('A'), ('1')) t (ValueText)
            WHERE   t.ValueText NOT LIKE '%[^0-9]%'
        ) t
WHERE   TRY_CONVERT(INT, ValueText) < 10;
SELECT  ValueText
FROM    (VALUES ('A'), ('1')) t (ValueText)
WHERE   TRY_CONVERT(INT, ValueText) < 10;
AND     t.ValueText NOT LIKE '%[^0-9]%';
SELECT  ValueText
FROM    (VALUES ('A'), ('1')) t (ValueText)
WHERE   ValueText < 10;
AND     t.ValueText NOT LIKE '%[^0-9]%';
DECLARE @T TABLE (ValueText INT)
INSERT @T (ValueText)
SELECT  ValueText
FROM    (VALUES ('A'), ('1')) t (ValueText)
WHERE   t.ValueText NOT LIKE '%[^0-9]%';

SELECT  *
FROM    @T
WHERE   ValueText < 10;
SELECT  ValueText
FROM    (   SELECT  TOP 2147483647 ValueText
            FROM    (VALUES ('A'), ('1')) t (ValueText)
            WHERE   t.ValueText NOT LIKE '%[^0-9]%'
        ) t
WHERE   ValueText < 10;
SELECT  *
FROM    (   SELECT  ValueText = CASE WHEN ValueText NOT LIKE '%[^0-9]%' THEN ValueText END
            FROM    (VALUES ('A'), ('1')) t (ValueText)
            WHERE   t.ValueText NOT LIKE '%[^0-9]%'
        ) t
WHERE   ValueText < 10;
SELECT ItemNumber 
FROM (
    SELECT case isnumeric(ItemNumber) 
        when 1 then CAST(ItemNumber AS int) 
        else -999999999
        end
        AS ItemNumber
    FROM vw_PDM_Union_Items
) AS x
WHERE ItemNumber < 800900000 
    and ItemNumber>-999999999