Query Syntax

  • Hi All

    I can across something today that I haven't encountered before (due to a typo in my syntax actually) and am interested in finding the answer to, consider the following:

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

    SET DATEFORMAT DMY

    DECLARE @TABLE1 AS TABLE

    (VALUE INT)

    INSERT INTO @TABLE1

    SELECT 1 UNION ALL

    SELECT 2 UNION ALL

    SELECT 3 UNION ALL

    SELECT 4

    DECLARE @TABLE2 AS TABLE

    (VALUE2 INT)

    INSERT INTO @TABLE2

    SELECT 1 UNION ALL

    SELECT 2 UNION ALL

    SELECT 3 UNION ALL

    SELECT 4

    DECLARE @TABLE3 AS TABLE

    (TEST INT)

    INSERT INTO @TABLE3

    SELECT 1 UNION ALL

    SELECT 2 UNION ALL

    SELECT 3 UNION ALL

    SELECT 4

    SELECT *

    FROM

    @TABLE1 AS T1

    INNER JOIN @TABLE2 AS T2

    ON T1.VALUE = T2.VALUE2

    WHERE

    T1.VALUE IN (SELECT VALUE FROM @TABLE3)

    How come this syntax runs, the column VALUE does not exist in TABLE3 and therefore I am not SELECTing anything from TABLE3?

    I of course know that subqueries can reference the outer query so it is essentially doing the following:

    WHERE

    T1.VALUE IN (SELECT T1.VALUE)

    I would have thought in the IN statement SELECT I would have to at least reference a valid column from TABLE3 or not SELECT a column at all i.e. change VALUE in the IN clause to a hard coded 1 or something which would be valid as the syntax would be SELECT 1 FROM Table3 which is valid? :crazy:

    As I said this is purely out of interest as I've never seen this before?

    Andy

    ==========================================================================================================================
    A computer lets you make more mistakes faster than any invention in human history - with the possible exceptions of handguns and tequila. Mitch Ratcliffe

  • Andy Hyslop (5/3/2012)


    How come this syntax runs, the column VALUE does not exist in TABLE3 and therefore I am not SELECTing anything from TABLE3?

    Because there's nothing in SQL that requires you to actually select data from a table referenced in the query

    I of course know that subqueries can reference the outer query so it is essentially doing the following:

    WHERE

    T1.VALUE IN (SELECT T1.VALUE)

    Exactly what it's doing

    I would have thought in the IN statement SELECT I would have to at least reference a valid column from TABLE3 or not SELECT a column at all i.e. change VALUE in the IN clause to a hard coded 1 or something which would be valid as the syntax would be SELECT 1 FROM Table3 which is valid? :crazy:

    No, all that's required is that any column is bindable to a table in scope, which it is.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • When I looked first it did looked strange, but in few seconds...

    see:

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

    SET DATEFORMAT DMY

    DECLARE @TABLE1 AS TABLE

    (VALUE INT)

    INSERT INTO @TABLE1

    SELECT 1 UNION ALL

    SELECT 2 UNION ALL

    SELECT 3 UNION ALL

    SELECT 4

    DECLARE @TABLE3 AS TABLE

    (TEST INT)

    INSERT INTO @TABLE3

    SELECT 0

    SELECT *

    FROM @TABLE1 AS T1

    WHERE T1.VALUE = (SELECT VALUE FROM @TABLE3)

    and

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

    SET DATEFORMAT DMY

    DECLARE @TABLE1 AS TABLE

    (VALUE1 INT)

    INSERT INTO @TABLE1

    SELECT 1 UNION ALL

    SELECT 2 UNION ALL

    SELECT 3 UNION ALL

    SELECT 4

    DECLARE @TABLE3 AS TABLE

    (TEST INT)

    INSERT INTO @TABLE3

    SELECT 0

    SELECT *

    FROM @TABLE1 AS T1

    WHERE T1.VALUE1 = (SELECT VALUE1 FROM @TABLE3)

    Can you see now which table "VALUE" column is selected from in the "IN"?

    _____________________________________________
    "The only true wisdom is in knowing you know nothing"
    "O skol'ko nam otkrytiy chudnyh prevnosit microsofta duh!":-D
    (So many miracle inventions provided by MS to us...)

    How to post your question to get the best and quick help[/url]

  • This is why you should always use qualify your column names.

    This would have thrown an error.

    SELECT *

    FROM @TABLE1 AS T1

    INNER JOIN @TABLE2 AS T2 ON T1.VALUE = T2.VALUE2

    WHERE T1.VALUE IN (SELECT T3.VALUE FROM @TABLE3 T3)

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • GilaMonster (5/3/2012)


    This is why you should always use qualify your column names.

    This would have thrown an error.

    SELECT *

    FROM @TABLE1 AS T1

    INNER JOIN @TABLE2 AS T2 ON T1.VALUE = T2.VALUE2

    WHERE T1.VALUE IN (SELECT T3.VALUE FROM @TABLE3 T3)

    I also use the simple rule:

    Query with one table involved - don't need alias,

    more than one table: alias for every table.

    It helps to prevent such "strange" behaviour...

    _____________________________________________
    "The only true wisdom is in knowing you know nothing"
    "O skol'ko nam otkrytiy chudnyh prevnosit microsofta duh!":-D
    (So many miracle inventions provided by MS to us...)

    How to post your question to get the best and quick help[/url]

  • Thanks both

    Eugene yep I knew what it was doing it was more a question of is this expected behaviour.

    OK dumb question then if all that is needed is to bind a table to a scope how come the following fails:

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

    SET DATEFORMAT DMY

    DECLARE @TABLE1 AS TABLE

    (VALUE INT)

    INSERT INTO @TABLE1

    SELECT 1 UNION ALL

    SELECT 2 UNION ALL

    SELECT 3 UNION ALL

    SELECT 4

    DECLARE @TABLE3 AS TABLE

    (TEST INT)

    INSERT INTO @TABLE3

    SELECT 1 UNION ALL

    SELECT 2 UNION ALL

    SELECT 3 UNION ALL

    SELECT 4

    SELECT *

    FROM

    @TABLE1 AS T1

    INNER JOIN(SELECT

    VALUE

    FROM

    @TABLE3

    ) AS T3

    ON T1.VALUE = T3.VALUE

    Now don't get me wrong I know it will fail as VALUE does not exist in TABLE3 however how come this syntax errors but place the same syntax in a WHERE and it will execute?

    I may be answering my own question here but is it because SQL evaluates inner subquery's before the outer query and as this column does not exist = Error..?

    Andy

    ==========================================================================================================================
    A computer lets you make more mistakes faster than any invention in human history - with the possible exceptions of handguns and tequila. Mitch Ratcliffe

  • Subqueries in the select and where are allowed to be correlated (to reference columns in the outer query). Subqueries in the from are not allowed to be correlated unless they are used with cross apply

    Your code fails, not because of order of evaluation, but simply because a subquery used with inner join is not allowed to be correlated.

    This works

    DECLARE @TABLE1 AS TABLE

    (VALUE INT)

    INSERT INTO @TABLE1

    SELECT 1 UNION ALL

    SELECT 2 UNION ALL

    SELECT 3 UNION ALL

    SELECT 4

    DECLARE @TABLE3 AS TABLE

    (TEST INT)

    INSERT INTO @TABLE3

    SELECT 1 UNION ALL

    SELECT 2 UNION ALL

    SELECT 3 UNION ALL

    SELECT 4

    SELECT *

    FROM

    @TABLE1 AS T1

    CROSS APPLY(SELECT

    T1.VALUE

    FROM

    @TABLE3

    ) AS T3

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • Gail thank-you, explained so well even I can understand it 😉

    I've been using T-SQL/ P-SQL for years and am by no means a beginner, although compared to some of you guys on this site who's knowledge of SQL is astounding I feel like it sometimes! :hehe:

    I'm completely self taught so sometimes I come across things like this and just have to know.....Why?!!!

    Only way to learn eh? 😉

    (well except for certification which I'm looking at next)

    Thanks again

    Andy

    Slight Edit: How come its allowed with a CROSS APPLY?

    ==========================================================================================================================
    A computer lets you make more mistakes faster than any invention in human history - with the possible exceptions of handguns and tequila. Mitch Ratcliffe

  • Because the whole point of cross apply it to allow the passing of a column from another table to a function or subquery.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • GilaMonster (5/3/2012)


    Because the whole point of cross apply it to allow the passing of a column from another table to a function or subquery.

    I've used CROSS APPLY many times in the past and knew its function my question was more of the internal process as to the how is it allowed.

    Thank-you again Gail, I've got some reading to do I think! I'll take it from here 😀

    ==========================================================================================================================
    A computer lets you make more mistakes faster than any invention in human history - with the possible exceptions of handguns and tequila. Mitch Ratcliffe

  • Nothing to say on the how, it's the same as any other correlated subquery.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass

Viewing 11 posts - 1 through 10 (of 10 total)

You must be logged in to reply to this topic. Login to reply