Domanda

I have two tables:

  • SupplierLocation with columns Id | SupplierId | ThirdPartyId

  • Supplier with columns Id | Company

We are using SQL Server 2008. I am trying to correct some badly written queries. For example, the following query runs without throwing an error, even though there is an incorrect column name in the subquery (Supplier table does not have ThirdPartyId):

SELECT * 
FROM SupplierLocation 
WHERE SupplierId IN (SELECT ThirdPartyId 
                     FROM Supplier 
                     WHERE Id = @id)

Is there a way to check that in a query like this the subquery is correct?

Thanks!

È stato utile?

Soluzione

Use aliases and qualify the column names.

SELECT * 
FROM SupplierLocation as SL
WHERE SL.SupplierId IN (SELECT S.ThirdPartyId 
                     FROM Supplier as S
                     WHERE S.Id = @id)

It is perfectly legitimate to include data from various sources in subqueries:

SELECT *, ( select Id + ThirdParty + @Id from Supplier where Id = @Id ) as GuessWhat
FROM SupplierLocation as SL
WHERE SL.SupplierId IN (SELECT S.ThirdPartyId 
                     FROM Supplier as S
                     WHERE S.Id = @id)

If you aren't explicit about the sources then you may be surprised to find what SQL Server can resolve. It is good practice whenever you use JOINs to qualify all column names.

The Parse tool in SSMS will detect some, but not all, errors. It is a handy starting point.

Altri suggerimenti

While not a universal solution to this issue, the example provided can be rewritten such that similar mistakes are caught by the query compiler.

One approach is to qualify column names.

SELECT * 
FROM SupplierLocation 
WHERE SupplierId IN (SELECT Supplier.ThirdPartyId 
    FROM Supplier 
    WHERE Id = @id)

Another is to use where exists instead of where in

SELECT * 
FROM SupplierLocation 
WHERE EXISTS (SELECT *
    FROM Supplier 
    WHERE ID = SupplierID
    AND ID = @ID)

(Of course in this example the subquery isn't even required. One could just check the SupplierID column against the @ID variable directly)

In a word: no - at least, no simple way.

If the code runs without throwing an error (but you happen to know that the output is incorrect) then there is an error in the application logic.

If the code runs without throwing an error and you don't know whether it's working correctly, there is no magic wand you can wave to validate it.

This is what testing is for: to check that code that runs is working correctly.

Code reviews can also help in this aim.

This should not happen but I could guess at some reasons why it might happen:

  1. SupplierLocation is empty so the query optimizer compiles a plan that doesn't include the subquery at all.

  2. You're only testing with @id values that don't exist in Supplier so the query optimizer knows that the subquery will always return no records and thus never gets as far as trying to extract a nonexistant column.

  3. The server is somehow using a cached plan (an old version) that does not mention the nonexistent column.

It seems much more likely that an error is in fact occuring but you're not seeing it for some reason.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top