mardi 14 juin 2016

Filtered Out String Still Causes Error in SQL Statement

I am using SQL Server 2008 R2.

I am writing a part number generator app. Our part numbers consist of a nine digit numeric value, such as 914602001. Before creating a new number, there are several sources that need to be checked if it already exists. To try and save time, I've created a simple union of some of these sources. The union is as follows:

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)

The first table, EngPartNumbers, was an Excel file that was imported into SQL. It contains one column, ItemNumber, and is of varchar data type. It has to be varchar because there was a point in time where we used letters in our naming convention.

The second table is looking to our EPDM, where VariableValue is the table that stores all of the values to our variables, which is housed in the Variables table. The ValueText column is a varchar that holds all of the variable values. In my case, I'm only concerned about 9 digit numeric values, so I applied the last line:

WHERE (ValueText NOT LIKE '%[^0-9]%') AND (LEN(ValueText) = 9) 

The results of the union is what I would expect; only numbers:

Query results from vw_PDM_Union_Items

This is where my problem is. Because I would like to get the next available number, I want to work with the int data type, not the varchar. When I select everything from my view, CAST the column as an int, and add a WHERE clause, like so:

SELECT ItemNumber 
FROM (
    SELECT CAST(ItemNumber AS int) AS ItemNumber 
    FROM vw_PDM_Union_Items
    ) AS x
WHERE ItemNumber < 800900000

I get the following error:

Conversion failed when converting the nvarchar value '"SW-Revision"' to data type int.

After research, I've noticed the "SW-Revision" refers to a value of a variable, which is stored in the ValueText column of the VariableValue table. To me, this shouldn't matter since I'm looking at my view which has already filtered out this bad data. I've even tried wrapping my view in a select statement that CASTs the column as an int, like so:

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]%')

but I still get the same error. Why is SQL acting this way? What is happening in the background that causes it to look at the original table? If anyone can shed light on this situation and give me a better way to accomplish this, it would be appreciated. For manipulation sake, I would like to work with an int column, rather than a varchar.

Thank you in advance.

Aucun commentaire:

Enregistrer un commentaire