Reputation: 532
I have declared a table within a stored procedure i.e :
DECLARE @fooTable table ( idfoo INT)
INSERT INTO @fooTable
EXEC getBOO
SELECT * FROM @fooTable
I want to join this table with other tables from my local server db i.e :
SELECT *
FROM tbl1
RIGHT JOIN tbl2 ON tbl1.foofield = tbl2.foofield
RIGHT JOIN @fooTable ON tbl2.foofield = @fooTable.foofield ;
I get an error:
Must declare the scalar variable "@fooTable"
I've searched a bit for this error, most of the posts I found stated that the table I'm trying to reach is out of scope.
Well the declaration of @fooTable
, as well as the JOIN query, are a part of the same stored procedure, so i can't find any scoping issues.
What is the best practise to JOIN a variable table (@fooTable) with tables from my local server ? (tbl1, tbl2) ?
Upvotes: 1
Views: 4212
Reputation: 57053
The issue here is a relation operation (join) on two tables with columns having the same name and type. In 1992, this problem was solved when new join syntax was introduced (NATURAL
, USING
, etc). Your query could be fixed in this way:
SELECT *
FROM tbl1
NATURAL RIGHT JOIN tbl2
NATURAL RIGHT JOIN @fooTable;
However, SQL Server has not adopted the 1992 join types so we are stuck with SQL's original resolution, dating back to the 1970s: range variables. [Others here are using the inappropriate term 'aliases' for the same concept.] To be clear: the user is required to use range variables to resolve the 'names in common' issue.
Though you may not realize it, you are using range variables in your code e.g. in the line
ON tbl1.foofield = tbl2.foofield
both tbl1
and tbl2
are range variables: each represents the row of the table which it ranges over. Because you didn't specify your own range variable names, the name of the table is used (again this has its roots in 1970s SQL) i.e. is equivalent to:
SELECT *
FROM tbl1 tbl1
RIGHT JOIN tbl2 tbl2
ON tbl1.foofield = tbl2.foofield
I guess where your code is falling down is that @fooTable
is not a valid range variable name i.e.
RIGHT JOIN @fooTable @fooTable
Therefore, the fix is to pick a range variable name that makes SQL Server happy e.g.
SELECT *
FROM tbl2 t2
RIGHT JOIN @fooTable f
ON t2.foofield = f.foofield
My preferred solution is for SQL Server to implement the 1992 join types! Not within my control but I have voted for it here.
Upvotes: 1
Reputation: 121
DECLARE @fooTable table ( idfoo INT)
INSERT INTO @fooTable
EXEC getBOO
SELECT * FROM @fooTable
SELECT *
FROM tbl1 RIGHT JOIN tbl2
ON tbl1.foofield = tbl2.foofield
RIGHT JOIN @fooTable f2
ON tbl2.foofield = f2.idfoo ;
Upvotes: 4
Reputation: 24222
You need to provide an alias for the table variable:
SELECT *
FROM tbl1 RIGHT JOIN tbl2
ON tbl1.foofield = tbl2.foofield
RIGHT JOIN @fooTable FooTable
ON tbl2.foofield = FooTable.foofield;
Upvotes: 1
Reputation: 93734
Just give a Alias
name to table variable and use it for reference
SELECT *
FROM tbl1
RIGHT JOIN tbl2
ON tbl1.foofield = tbl2.foofield
RIGHT JOIN @fooTable FT -- Here
ON tbl2.foofield = FT.foofield;
--^^-- Here
Upvotes: 3