“Must declare the table variable ”@name“” in stored procedure












13















I have a procedure which returns the error:




Must declare the table variable "@PropIDs".




But it is followed with the message:




(123 row(s) affected)




The error appears when I execute it with



EXEC [dbo].[GetNeededProperties] '1,3,5,7,2,12', '06/28/2013', 'TT'


But works fine when



EXEC [dbo].[GetNeededProperties] NULL, '06/28/2013', 'TT'


Can any one help me with that?
The procedure:



CREATE PROCEDURE [dbo].[GetNeededProperties]
@NotNeededWPRNs nvarchar(max), --string like '1,2,3,4,5'
@LastSynch datetime,
@TechCode varchar(5)
AS
BEGIN

DECLARE @PropIDs TABLE
(ID bigint)
Declare @ProductsSQL nvarchar(max);
SET @ProductsSQL = 'Insert into @PropIDs (ID)
SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))'
exec sp_executesql @ProductsSQL

SELECT p.WPRN AS ID,
p.Address AS Address,
p.Address AS Street
FROM [dbo].[Properties] AS p
WHERE
p.WPRN NOT IN( SELECT ID FROM @PropIDs)




I've found kind of solution when declaring table like this:



IF OBJECT_ID('#PropIDs', 'U') IS NOT NULL
DROP TABLE #PropIDs

CREATE TABLE #PropIDs


But when execute the procedure from C# (linq sql) it returns an error










share|improve this question

























  • Show how are you invoking SP from c#?

    – Anatolii Gabuza
    Nov 28 '13 at 11:33











  • When you create a temp table with the # the way you have its actually stored in sql server and needs to be deleted once you are done using it, the temp table you have created is a scalar variable and is propbably inaccessible at that point

    – liquidsnake786
    Nov 28 '13 at 11:35






  • 1





    Small thing: when you declare your dynamic SQL variable as nvarchar, you should use N to declare string literals: N'Insert into... or it won't use Unicode

    – Szymon
    Nov 28 '13 at 11:36








  • 1





    '1,3,5,7,2,12' is a single string that you're passing to your stored procedure, but the IN (....) operator expects a list of values - not a single string! You should be using a table-valued parameter for your ID's which allows you to pass in multiple values from the caller in a proper, well-defined way, and then you don't need to resort to dynamic SQL, either! TVP's are available in SQL Server 2008 and newer.

    – marc_s
    Nov 28 '13 at 11:42













  • As an aside, unless you are working in the TempDB you will need to prefix your temp table with TempDB.. in this line IF OBJECT_ID('#PropIDs', 'U') IS NOT NULL, i.e. IF OBJECT_ID('TempDB..#PropIDs', 'U') IS NOT NULL

    – GarethD
    Nov 28 '13 at 11:56
















13















I have a procedure which returns the error:




Must declare the table variable "@PropIDs".




But it is followed with the message:




(123 row(s) affected)




The error appears when I execute it with



EXEC [dbo].[GetNeededProperties] '1,3,5,7,2,12', '06/28/2013', 'TT'


But works fine when



EXEC [dbo].[GetNeededProperties] NULL, '06/28/2013', 'TT'


Can any one help me with that?
The procedure:



CREATE PROCEDURE [dbo].[GetNeededProperties]
@NotNeededWPRNs nvarchar(max), --string like '1,2,3,4,5'
@LastSynch datetime,
@TechCode varchar(5)
AS
BEGIN

DECLARE @PropIDs TABLE
(ID bigint)
Declare @ProductsSQL nvarchar(max);
SET @ProductsSQL = 'Insert into @PropIDs (ID)
SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))'
exec sp_executesql @ProductsSQL

SELECT p.WPRN AS ID,
p.Address AS Address,
p.Address AS Street
FROM [dbo].[Properties] AS p
WHERE
p.WPRN NOT IN( SELECT ID FROM @PropIDs)




I've found kind of solution when declaring table like this:



IF OBJECT_ID('#PropIDs', 'U') IS NOT NULL
DROP TABLE #PropIDs

CREATE TABLE #PropIDs


But when execute the procedure from C# (linq sql) it returns an error










share|improve this question

























  • Show how are you invoking SP from c#?

    – Anatolii Gabuza
    Nov 28 '13 at 11:33











  • When you create a temp table with the # the way you have its actually stored in sql server and needs to be deleted once you are done using it, the temp table you have created is a scalar variable and is propbably inaccessible at that point

    – liquidsnake786
    Nov 28 '13 at 11:35






  • 1





    Small thing: when you declare your dynamic SQL variable as nvarchar, you should use N to declare string literals: N'Insert into... or it won't use Unicode

    – Szymon
    Nov 28 '13 at 11:36








  • 1





    '1,3,5,7,2,12' is a single string that you're passing to your stored procedure, but the IN (....) operator expects a list of values - not a single string! You should be using a table-valued parameter for your ID's which allows you to pass in multiple values from the caller in a proper, well-defined way, and then you don't need to resort to dynamic SQL, either! TVP's are available in SQL Server 2008 and newer.

    – marc_s
    Nov 28 '13 at 11:42













  • As an aside, unless you are working in the TempDB you will need to prefix your temp table with TempDB.. in this line IF OBJECT_ID('#PropIDs', 'U') IS NOT NULL, i.e. IF OBJECT_ID('TempDB..#PropIDs', 'U') IS NOT NULL

    – GarethD
    Nov 28 '13 at 11:56














13












13








13


2






I have a procedure which returns the error:




Must declare the table variable "@PropIDs".




But it is followed with the message:




(123 row(s) affected)




The error appears when I execute it with



EXEC [dbo].[GetNeededProperties] '1,3,5,7,2,12', '06/28/2013', 'TT'


But works fine when



EXEC [dbo].[GetNeededProperties] NULL, '06/28/2013', 'TT'


Can any one help me with that?
The procedure:



CREATE PROCEDURE [dbo].[GetNeededProperties]
@NotNeededWPRNs nvarchar(max), --string like '1,2,3,4,5'
@LastSynch datetime,
@TechCode varchar(5)
AS
BEGIN

DECLARE @PropIDs TABLE
(ID bigint)
Declare @ProductsSQL nvarchar(max);
SET @ProductsSQL = 'Insert into @PropIDs (ID)
SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))'
exec sp_executesql @ProductsSQL

SELECT p.WPRN AS ID,
p.Address AS Address,
p.Address AS Street
FROM [dbo].[Properties] AS p
WHERE
p.WPRN NOT IN( SELECT ID FROM @PropIDs)




I've found kind of solution when declaring table like this:



IF OBJECT_ID('#PropIDs', 'U') IS NOT NULL
DROP TABLE #PropIDs

CREATE TABLE #PropIDs


But when execute the procedure from C# (linq sql) it returns an error










share|improve this question
















I have a procedure which returns the error:




Must declare the table variable "@PropIDs".




But it is followed with the message:




(123 row(s) affected)




The error appears when I execute it with



EXEC [dbo].[GetNeededProperties] '1,3,5,7,2,12', '06/28/2013', 'TT'


But works fine when



EXEC [dbo].[GetNeededProperties] NULL, '06/28/2013', 'TT'


Can any one help me with that?
The procedure:



CREATE PROCEDURE [dbo].[GetNeededProperties]
@NotNeededWPRNs nvarchar(max), --string like '1,2,3,4,5'
@LastSynch datetime,
@TechCode varchar(5)
AS
BEGIN

DECLARE @PropIDs TABLE
(ID bigint)
Declare @ProductsSQL nvarchar(max);
SET @ProductsSQL = 'Insert into @PropIDs (ID)
SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))'
exec sp_executesql @ProductsSQL

SELECT p.WPRN AS ID,
p.Address AS Address,
p.Address AS Street
FROM [dbo].[Properties] AS p
WHERE
p.WPRN NOT IN( SELECT ID FROM @PropIDs)




I've found kind of solution when declaring table like this:



IF OBJECT_ID('#PropIDs', 'U') IS NOT NULL
DROP TABLE #PropIDs

CREATE TABLE #PropIDs


But when execute the procedure from C# (linq sql) it returns an error







sql sql-server






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 28 '13 at 11:44









Albireo

8,26195283




8,26195283










asked Nov 28 '13 at 11:30









TomTom

295127




295127













  • Show how are you invoking SP from c#?

    – Anatolii Gabuza
    Nov 28 '13 at 11:33











  • When you create a temp table with the # the way you have its actually stored in sql server and needs to be deleted once you are done using it, the temp table you have created is a scalar variable and is propbably inaccessible at that point

    – liquidsnake786
    Nov 28 '13 at 11:35






  • 1





    Small thing: when you declare your dynamic SQL variable as nvarchar, you should use N to declare string literals: N'Insert into... or it won't use Unicode

    – Szymon
    Nov 28 '13 at 11:36








  • 1





    '1,3,5,7,2,12' is a single string that you're passing to your stored procedure, but the IN (....) operator expects a list of values - not a single string! You should be using a table-valued parameter for your ID's which allows you to pass in multiple values from the caller in a proper, well-defined way, and then you don't need to resort to dynamic SQL, either! TVP's are available in SQL Server 2008 and newer.

    – marc_s
    Nov 28 '13 at 11:42













  • As an aside, unless you are working in the TempDB you will need to prefix your temp table with TempDB.. in this line IF OBJECT_ID('#PropIDs', 'U') IS NOT NULL, i.e. IF OBJECT_ID('TempDB..#PropIDs', 'U') IS NOT NULL

    – GarethD
    Nov 28 '13 at 11:56



















  • Show how are you invoking SP from c#?

    – Anatolii Gabuza
    Nov 28 '13 at 11:33











  • When you create a temp table with the # the way you have its actually stored in sql server and needs to be deleted once you are done using it, the temp table you have created is a scalar variable and is propbably inaccessible at that point

    – liquidsnake786
    Nov 28 '13 at 11:35






  • 1





    Small thing: when you declare your dynamic SQL variable as nvarchar, you should use N to declare string literals: N'Insert into... or it won't use Unicode

    – Szymon
    Nov 28 '13 at 11:36








  • 1





    '1,3,5,7,2,12' is a single string that you're passing to your stored procedure, but the IN (....) operator expects a list of values - not a single string! You should be using a table-valued parameter for your ID's which allows you to pass in multiple values from the caller in a proper, well-defined way, and then you don't need to resort to dynamic SQL, either! TVP's are available in SQL Server 2008 and newer.

    – marc_s
    Nov 28 '13 at 11:42













  • As an aside, unless you are working in the TempDB you will need to prefix your temp table with TempDB.. in this line IF OBJECT_ID('#PropIDs', 'U') IS NOT NULL, i.e. IF OBJECT_ID('TempDB..#PropIDs', 'U') IS NOT NULL

    – GarethD
    Nov 28 '13 at 11:56

















Show how are you invoking SP from c#?

– Anatolii Gabuza
Nov 28 '13 at 11:33





Show how are you invoking SP from c#?

– Anatolii Gabuza
Nov 28 '13 at 11:33













When you create a temp table with the # the way you have its actually stored in sql server and needs to be deleted once you are done using it, the temp table you have created is a scalar variable and is propbably inaccessible at that point

– liquidsnake786
Nov 28 '13 at 11:35





When you create a temp table with the # the way you have its actually stored in sql server and needs to be deleted once you are done using it, the temp table you have created is a scalar variable and is propbably inaccessible at that point

– liquidsnake786
Nov 28 '13 at 11:35




1




1





Small thing: when you declare your dynamic SQL variable as nvarchar, you should use N to declare string literals: N'Insert into... or it won't use Unicode

– Szymon
Nov 28 '13 at 11:36







Small thing: when you declare your dynamic SQL variable as nvarchar, you should use N to declare string literals: N'Insert into... or it won't use Unicode

– Szymon
Nov 28 '13 at 11:36






1




1





'1,3,5,7,2,12' is a single string that you're passing to your stored procedure, but the IN (....) operator expects a list of values - not a single string! You should be using a table-valued parameter for your ID's which allows you to pass in multiple values from the caller in a proper, well-defined way, and then you don't need to resort to dynamic SQL, either! TVP's are available in SQL Server 2008 and newer.

– marc_s
Nov 28 '13 at 11:42







'1,3,5,7,2,12' is a single string that you're passing to your stored procedure, but the IN (....) operator expects a list of values - not a single string! You should be using a table-valued parameter for your ID's which allows you to pass in multiple values from the caller in a proper, well-defined way, and then you don't need to resort to dynamic SQL, either! TVP's are available in SQL Server 2008 and newer.

– marc_s
Nov 28 '13 at 11:42















As an aside, unless you are working in the TempDB you will need to prefix your temp table with TempDB.. in this line IF OBJECT_ID('#PropIDs', 'U') IS NOT NULL, i.e. IF OBJECT_ID('TempDB..#PropIDs', 'U') IS NOT NULL

– GarethD
Nov 28 '13 at 11:56





As an aside, unless you are working in the TempDB you will need to prefix your temp table with TempDB.. in this line IF OBJECT_ID('#PropIDs', 'U') IS NOT NULL, i.e. IF OBJECT_ID('TempDB..#PropIDs', 'U') IS NOT NULL

– GarethD
Nov 28 '13 at 11:56












4 Answers
4






active

oldest

votes


















13














The issue is that you're mixing up dynamic SQL with non-dynamic SQL.



Firstly - the reason it works when you put NULL into @NotNeededWPRNs is because when that variable is NULL, your @ProductsSQL becomes NULL.



WHat you need to do is either make your @PropsIDs table a non-table variable and either a temporary table or a physical table.
OR
you need to wrap everything in dynamic SQL and execute it.



So the easy way is to do something like this:



Declare @ProductsSQL nvarchar(max);
SET @ProductsSQL = '
DECLARE @PropIDs TABLE
(ID bigint)
Insert into @PropIDs (ID)
SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))

SELECT p.WPRN AS ID,
p.Address AS Address,
p.Address AS Street
FROM [dbo].[Properties] AS p
WHERE
p.WPRN NOT IN( SELECT ID FROM @PropIDs)
'


and execute that.
OR as mentioned - change @ProdIDs to a temporary table. (The route you're approaching in the CREATE #ProdIds, but then you need to use #ProdIDs instead of @ProdIDs everywhere in the sproc).






share|improve this answer
























  • thanks, it works now with temp table '#ProdIDs' . I haven't try the first solution but i will do that because I'm not sure how it will work with linq

    – Tom
    Nov 28 '13 at 12:11



















5














The reason you get this error is that the scope of table variables is limited to a single batch, since sp_executesql runs in its own batch, it has no knowledge that you have declared it in another batch.



It works when you @NotNeededWPRNs is NULL because concatenating NULL yields NULL (unless otherwise set), so you are just executing:



exec sp_executesql null;


I would also say, if you are using SQL Server 2008 or later please consider using table valued parameters instead of a delimited list of strings. This is much safer and more efficient, and validates the input, if I were to pass 1); DROP TABLE dbo.Prioperties; -- as @NotNeededWPRNs, you could find yourself without a properties table.



First you would need to create the type (I tend to use a generic name for reusability):



CREATE TYPE dbo.IntegerList TABLE (Value INT);


Then you can add it to your procedure:



CREATE PROCEDURE [dbo].[GetNeededProperties]
@NotNeededWPRNs dbo.IntegerList READONLY,
@LastSynch DATETIME,
@TechCode VARCHAR(5)
AS
BEGIN

SELECT p.WPRN AS ID,
p.Address AS Address,
p.Address AS Street
FROM [dbo].[Properties] AS p
WHERE p.WPRN NOT IN (SELECT Value FROM @NotNeededWPRNs)


On an unrelated note, you should avoid using culture sensitive date formats where possible, 06/28/2013 is clearly supposed to be 28th June in this case, but what about 06/07/2013, without setting DATEFORMAT, or the language how do you know if this will be read as 6th July or 7th June? The best format to use is yyyyMMdd, it is never ambiguous, even the ISO standard format yyyy-MM-dd can be interpreted as yyyy-dd-MM in some settings.






share|improve this answer


























  • thanks for all suggestions - now I've managed to make it work but I will get back to this to make some improvements

    – Tom
    Nov 28 '13 at 12:15



















1














Change you code to :



Declare @ProductsSQL nvarchar(max);
SET @ProductsSQL = 'DECLARE @PropIDs TABLE
(ID bigint);
Insert into @PropIDs (ID)
SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))'
exec sp_executesql @ProductsSQL


Table variable declared outside the dynamic SQL will not be available to the dynamic SQL.






share|improve this answer
























  • Correct. I was only trying to point out what the problem was. Not rewriting the code for him :)

    – Raj
    Nov 28 '13 at 11:38











  • Thanks - now it works when i execute it using EXEC. Nut I'm getting an exception when executing it from C# now Exception: System.Data.SqlClient.SqlException: Incorrect syntax near ')'. Do you have any idea what might cause that?

    – Tom
    Nov 28 '13 at 11:40











  • never mind -the error was caused by empty (but not null) string parameter: ''

    – Tom
    Nov 28 '13 at 12:00



















0














You can avoid using dynamic sql by creating a sql function that use a CTE (I found the code below many years ago on sqlservercentral - Amit Gaur) :



Change the body of your procs with something like this :



SELECT  p.WPRN AS ID,
p.Address AS Address,
p.Address AS Street
FROM [dbo].[Properties] AS p
WHERE
p.WPRN NOT IN ( SELECT item FROM dbo.strToTable(@NotNeededWPRNs, ','))


Below the sql code that transforms a string into a table :



CREATE FUNCTION [dbo].[strToTable] 
(
@array varchar(max),
@del char(1)
)
RETURNS
@listTable TABLE
(
item int
)
AS
BEGIN

WITH rep (item,list) AS
(
SELECT SUBSTRING(@array,1,CHARINDEX(@del,@array,1) - 1) as item,
SUBSTRING(@array,CHARINDEX(@del,@array,1) + 1, LEN(@array)) + @del list

UNION ALL

SELECT SUBSTRING(list,1,CHARINDEX(@del,list,1) - 1) as item,
SUBSTRING(list,CHARINDEX(@del,list,1) + 1, LEN(list)) list
FROM rep
WHERE LEN(rep.list) > 0
)
INSERT INTO @listTable
SELECT item FROM rep

RETURN
END





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f20265023%2fmust-declare-the-table-variable-name-in-stored-procedure%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    13














    The issue is that you're mixing up dynamic SQL with non-dynamic SQL.



    Firstly - the reason it works when you put NULL into @NotNeededWPRNs is because when that variable is NULL, your @ProductsSQL becomes NULL.



    WHat you need to do is either make your @PropsIDs table a non-table variable and either a temporary table or a physical table.
    OR
    you need to wrap everything in dynamic SQL and execute it.



    So the easy way is to do something like this:



    Declare @ProductsSQL nvarchar(max);
    SET @ProductsSQL = '
    DECLARE @PropIDs TABLE
    (ID bigint)
    Insert into @PropIDs (ID)
    SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))

    SELECT p.WPRN AS ID,
    p.Address AS Address,
    p.Address AS Street
    FROM [dbo].[Properties] AS p
    WHERE
    p.WPRN NOT IN( SELECT ID FROM @PropIDs)
    '


    and execute that.
    OR as mentioned - change @ProdIDs to a temporary table. (The route you're approaching in the CREATE #ProdIds, but then you need to use #ProdIDs instead of @ProdIDs everywhere in the sproc).






    share|improve this answer
























    • thanks, it works now with temp table '#ProdIDs' . I haven't try the first solution but i will do that because I'm not sure how it will work with linq

      – Tom
      Nov 28 '13 at 12:11
















    13














    The issue is that you're mixing up dynamic SQL with non-dynamic SQL.



    Firstly - the reason it works when you put NULL into @NotNeededWPRNs is because when that variable is NULL, your @ProductsSQL becomes NULL.



    WHat you need to do is either make your @PropsIDs table a non-table variable and either a temporary table or a physical table.
    OR
    you need to wrap everything in dynamic SQL and execute it.



    So the easy way is to do something like this:



    Declare @ProductsSQL nvarchar(max);
    SET @ProductsSQL = '
    DECLARE @PropIDs TABLE
    (ID bigint)
    Insert into @PropIDs (ID)
    SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))

    SELECT p.WPRN AS ID,
    p.Address AS Address,
    p.Address AS Street
    FROM [dbo].[Properties] AS p
    WHERE
    p.WPRN NOT IN( SELECT ID FROM @PropIDs)
    '


    and execute that.
    OR as mentioned - change @ProdIDs to a temporary table. (The route you're approaching in the CREATE #ProdIds, but then you need to use #ProdIDs instead of @ProdIDs everywhere in the sproc).






    share|improve this answer
























    • thanks, it works now with temp table '#ProdIDs' . I haven't try the first solution but i will do that because I'm not sure how it will work with linq

      – Tom
      Nov 28 '13 at 12:11














    13












    13








    13







    The issue is that you're mixing up dynamic SQL with non-dynamic SQL.



    Firstly - the reason it works when you put NULL into @NotNeededWPRNs is because when that variable is NULL, your @ProductsSQL becomes NULL.



    WHat you need to do is either make your @PropsIDs table a non-table variable and either a temporary table or a physical table.
    OR
    you need to wrap everything in dynamic SQL and execute it.



    So the easy way is to do something like this:



    Declare @ProductsSQL nvarchar(max);
    SET @ProductsSQL = '
    DECLARE @PropIDs TABLE
    (ID bigint)
    Insert into @PropIDs (ID)
    SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))

    SELECT p.WPRN AS ID,
    p.Address AS Address,
    p.Address AS Street
    FROM [dbo].[Properties] AS p
    WHERE
    p.WPRN NOT IN( SELECT ID FROM @PropIDs)
    '


    and execute that.
    OR as mentioned - change @ProdIDs to a temporary table. (The route you're approaching in the CREATE #ProdIds, but then you need to use #ProdIDs instead of @ProdIDs everywhere in the sproc).






    share|improve this answer













    The issue is that you're mixing up dynamic SQL with non-dynamic SQL.



    Firstly - the reason it works when you put NULL into @NotNeededWPRNs is because when that variable is NULL, your @ProductsSQL becomes NULL.



    WHat you need to do is either make your @PropsIDs table a non-table variable and either a temporary table or a physical table.
    OR
    you need to wrap everything in dynamic SQL and execute it.



    So the easy way is to do something like this:



    Declare @ProductsSQL nvarchar(max);
    SET @ProductsSQL = '
    DECLARE @PropIDs TABLE
    (ID bigint)
    Insert into @PropIDs (ID)
    SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))

    SELECT p.WPRN AS ID,
    p.Address AS Address,
    p.Address AS Street
    FROM [dbo].[Properties] AS p
    WHERE
    p.WPRN NOT IN( SELECT ID FROM @PropIDs)
    '


    and execute that.
    OR as mentioned - change @ProdIDs to a temporary table. (The route you're approaching in the CREATE #ProdIds, but then you need to use #ProdIDs instead of @ProdIDs everywhere in the sproc).







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 28 '13 at 11:36









    Allan S. HansenAllan S. Hansen

    3,6721319




    3,6721319













    • thanks, it works now with temp table '#ProdIDs' . I haven't try the first solution but i will do that because I'm not sure how it will work with linq

      – Tom
      Nov 28 '13 at 12:11



















    • thanks, it works now with temp table '#ProdIDs' . I haven't try the first solution but i will do that because I'm not sure how it will work with linq

      – Tom
      Nov 28 '13 at 12:11

















    thanks, it works now with temp table '#ProdIDs' . I haven't try the first solution but i will do that because I'm not sure how it will work with linq

    – Tom
    Nov 28 '13 at 12:11





    thanks, it works now with temp table '#ProdIDs' . I haven't try the first solution but i will do that because I'm not sure how it will work with linq

    – Tom
    Nov 28 '13 at 12:11













    5














    The reason you get this error is that the scope of table variables is limited to a single batch, since sp_executesql runs in its own batch, it has no knowledge that you have declared it in another batch.



    It works when you @NotNeededWPRNs is NULL because concatenating NULL yields NULL (unless otherwise set), so you are just executing:



    exec sp_executesql null;


    I would also say, if you are using SQL Server 2008 or later please consider using table valued parameters instead of a delimited list of strings. This is much safer and more efficient, and validates the input, if I were to pass 1); DROP TABLE dbo.Prioperties; -- as @NotNeededWPRNs, you could find yourself without a properties table.



    First you would need to create the type (I tend to use a generic name for reusability):



    CREATE TYPE dbo.IntegerList TABLE (Value INT);


    Then you can add it to your procedure:



    CREATE PROCEDURE [dbo].[GetNeededProperties]
    @NotNeededWPRNs dbo.IntegerList READONLY,
    @LastSynch DATETIME,
    @TechCode VARCHAR(5)
    AS
    BEGIN

    SELECT p.WPRN AS ID,
    p.Address AS Address,
    p.Address AS Street
    FROM [dbo].[Properties] AS p
    WHERE p.WPRN NOT IN (SELECT Value FROM @NotNeededWPRNs)


    On an unrelated note, you should avoid using culture sensitive date formats where possible, 06/28/2013 is clearly supposed to be 28th June in this case, but what about 06/07/2013, without setting DATEFORMAT, or the language how do you know if this will be read as 6th July or 7th June? The best format to use is yyyyMMdd, it is never ambiguous, even the ISO standard format yyyy-MM-dd can be interpreted as yyyy-dd-MM in some settings.






    share|improve this answer


























    • thanks for all suggestions - now I've managed to make it work but I will get back to this to make some improvements

      – Tom
      Nov 28 '13 at 12:15
















    5














    The reason you get this error is that the scope of table variables is limited to a single batch, since sp_executesql runs in its own batch, it has no knowledge that you have declared it in another batch.



    It works when you @NotNeededWPRNs is NULL because concatenating NULL yields NULL (unless otherwise set), so you are just executing:



    exec sp_executesql null;


    I would also say, if you are using SQL Server 2008 or later please consider using table valued parameters instead of a delimited list of strings. This is much safer and more efficient, and validates the input, if I were to pass 1); DROP TABLE dbo.Prioperties; -- as @NotNeededWPRNs, you could find yourself without a properties table.



    First you would need to create the type (I tend to use a generic name for reusability):



    CREATE TYPE dbo.IntegerList TABLE (Value INT);


    Then you can add it to your procedure:



    CREATE PROCEDURE [dbo].[GetNeededProperties]
    @NotNeededWPRNs dbo.IntegerList READONLY,
    @LastSynch DATETIME,
    @TechCode VARCHAR(5)
    AS
    BEGIN

    SELECT p.WPRN AS ID,
    p.Address AS Address,
    p.Address AS Street
    FROM [dbo].[Properties] AS p
    WHERE p.WPRN NOT IN (SELECT Value FROM @NotNeededWPRNs)


    On an unrelated note, you should avoid using culture sensitive date formats where possible, 06/28/2013 is clearly supposed to be 28th June in this case, but what about 06/07/2013, without setting DATEFORMAT, or the language how do you know if this will be read as 6th July or 7th June? The best format to use is yyyyMMdd, it is never ambiguous, even the ISO standard format yyyy-MM-dd can be interpreted as yyyy-dd-MM in some settings.






    share|improve this answer


























    • thanks for all suggestions - now I've managed to make it work but I will get back to this to make some improvements

      – Tom
      Nov 28 '13 at 12:15














    5












    5








    5







    The reason you get this error is that the scope of table variables is limited to a single batch, since sp_executesql runs in its own batch, it has no knowledge that you have declared it in another batch.



    It works when you @NotNeededWPRNs is NULL because concatenating NULL yields NULL (unless otherwise set), so you are just executing:



    exec sp_executesql null;


    I would also say, if you are using SQL Server 2008 or later please consider using table valued parameters instead of a delimited list of strings. This is much safer and more efficient, and validates the input, if I were to pass 1); DROP TABLE dbo.Prioperties; -- as @NotNeededWPRNs, you could find yourself without a properties table.



    First you would need to create the type (I tend to use a generic name for reusability):



    CREATE TYPE dbo.IntegerList TABLE (Value INT);


    Then you can add it to your procedure:



    CREATE PROCEDURE [dbo].[GetNeededProperties]
    @NotNeededWPRNs dbo.IntegerList READONLY,
    @LastSynch DATETIME,
    @TechCode VARCHAR(5)
    AS
    BEGIN

    SELECT p.WPRN AS ID,
    p.Address AS Address,
    p.Address AS Street
    FROM [dbo].[Properties] AS p
    WHERE p.WPRN NOT IN (SELECT Value FROM @NotNeededWPRNs)


    On an unrelated note, you should avoid using culture sensitive date formats where possible, 06/28/2013 is clearly supposed to be 28th June in this case, but what about 06/07/2013, without setting DATEFORMAT, or the language how do you know if this will be read as 6th July or 7th June? The best format to use is yyyyMMdd, it is never ambiguous, even the ISO standard format yyyy-MM-dd can be interpreted as yyyy-dd-MM in some settings.






    share|improve this answer















    The reason you get this error is that the scope of table variables is limited to a single batch, since sp_executesql runs in its own batch, it has no knowledge that you have declared it in another batch.



    It works when you @NotNeededWPRNs is NULL because concatenating NULL yields NULL (unless otherwise set), so you are just executing:



    exec sp_executesql null;


    I would also say, if you are using SQL Server 2008 or later please consider using table valued parameters instead of a delimited list of strings. This is much safer and more efficient, and validates the input, if I were to pass 1); DROP TABLE dbo.Prioperties; -- as @NotNeededWPRNs, you could find yourself without a properties table.



    First you would need to create the type (I tend to use a generic name for reusability):



    CREATE TYPE dbo.IntegerList TABLE (Value INT);


    Then you can add it to your procedure:



    CREATE PROCEDURE [dbo].[GetNeededProperties]
    @NotNeededWPRNs dbo.IntegerList READONLY,
    @LastSynch DATETIME,
    @TechCode VARCHAR(5)
    AS
    BEGIN

    SELECT p.WPRN AS ID,
    p.Address AS Address,
    p.Address AS Street
    FROM [dbo].[Properties] AS p
    WHERE p.WPRN NOT IN (SELECT Value FROM @NotNeededWPRNs)


    On an unrelated note, you should avoid using culture sensitive date formats where possible, 06/28/2013 is clearly supposed to be 28th June in this case, but what about 06/07/2013, without setting DATEFORMAT, or the language how do you know if this will be read as 6th July or 7th June? The best format to use is yyyyMMdd, it is never ambiguous, even the ISO standard format yyyy-MM-dd can be interpreted as yyyy-dd-MM in some settings.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 28 '13 at 11:54

























    answered Nov 28 '13 at 11:41









    GarethDGarethD

    52.8k66090




    52.8k66090













    • thanks for all suggestions - now I've managed to make it work but I will get back to this to make some improvements

      – Tom
      Nov 28 '13 at 12:15



















    • thanks for all suggestions - now I've managed to make it work but I will get back to this to make some improvements

      – Tom
      Nov 28 '13 at 12:15

















    thanks for all suggestions - now I've managed to make it work but I will get back to this to make some improvements

    – Tom
    Nov 28 '13 at 12:15





    thanks for all suggestions - now I've managed to make it work but I will get back to this to make some improvements

    – Tom
    Nov 28 '13 at 12:15











    1














    Change you code to :



    Declare @ProductsSQL nvarchar(max);
    SET @ProductsSQL = 'DECLARE @PropIDs TABLE
    (ID bigint);
    Insert into @PropIDs (ID)
    SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))'
    exec sp_executesql @ProductsSQL


    Table variable declared outside the dynamic SQL will not be available to the dynamic SQL.






    share|improve this answer
























    • Correct. I was only trying to point out what the problem was. Not rewriting the code for him :)

      – Raj
      Nov 28 '13 at 11:38











    • Thanks - now it works when i execute it using EXEC. Nut I'm getting an exception when executing it from C# now Exception: System.Data.SqlClient.SqlException: Incorrect syntax near ')'. Do you have any idea what might cause that?

      – Tom
      Nov 28 '13 at 11:40











    • never mind -the error was caused by empty (but not null) string parameter: ''

      – Tom
      Nov 28 '13 at 12:00
















    1














    Change you code to :



    Declare @ProductsSQL nvarchar(max);
    SET @ProductsSQL = 'DECLARE @PropIDs TABLE
    (ID bigint);
    Insert into @PropIDs (ID)
    SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))'
    exec sp_executesql @ProductsSQL


    Table variable declared outside the dynamic SQL will not be available to the dynamic SQL.






    share|improve this answer
























    • Correct. I was only trying to point out what the problem was. Not rewriting the code for him :)

      – Raj
      Nov 28 '13 at 11:38











    • Thanks - now it works when i execute it using EXEC. Nut I'm getting an exception when executing it from C# now Exception: System.Data.SqlClient.SqlException: Incorrect syntax near ')'. Do you have any idea what might cause that?

      – Tom
      Nov 28 '13 at 11:40











    • never mind -the error was caused by empty (but not null) string parameter: ''

      – Tom
      Nov 28 '13 at 12:00














    1












    1








    1







    Change you code to :



    Declare @ProductsSQL nvarchar(max);
    SET @ProductsSQL = 'DECLARE @PropIDs TABLE
    (ID bigint);
    Insert into @PropIDs (ID)
    SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))'
    exec sp_executesql @ProductsSQL


    Table variable declared outside the dynamic SQL will not be available to the dynamic SQL.






    share|improve this answer













    Change you code to :



    Declare @ProductsSQL nvarchar(max);
    SET @ProductsSQL = 'DECLARE @PropIDs TABLE
    (ID bigint);
    Insert into @PropIDs (ID)
    SELECT [WPRN] FROM [dbo].[Properties] WHERE(WPRN in (' + @NotNeededWPRNs + '))'
    exec sp_executesql @ProductsSQL


    Table variable declared outside the dynamic SQL will not be available to the dynamic SQL.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 28 '13 at 11:34









    RajRaj

    8,62623447




    8,62623447













    • Correct. I was only trying to point out what the problem was. Not rewriting the code for him :)

      – Raj
      Nov 28 '13 at 11:38











    • Thanks - now it works when i execute it using EXEC. Nut I'm getting an exception when executing it from C# now Exception: System.Data.SqlClient.SqlException: Incorrect syntax near ')'. Do you have any idea what might cause that?

      – Tom
      Nov 28 '13 at 11:40











    • never mind -the error was caused by empty (but not null) string parameter: ''

      – Tom
      Nov 28 '13 at 12:00



















    • Correct. I was only trying to point out what the problem was. Not rewriting the code for him :)

      – Raj
      Nov 28 '13 at 11:38











    • Thanks - now it works when i execute it using EXEC. Nut I'm getting an exception when executing it from C# now Exception: System.Data.SqlClient.SqlException: Incorrect syntax near ')'. Do you have any idea what might cause that?

      – Tom
      Nov 28 '13 at 11:40











    • never mind -the error was caused by empty (but not null) string parameter: ''

      – Tom
      Nov 28 '13 at 12:00

















    Correct. I was only trying to point out what the problem was. Not rewriting the code for him :)

    – Raj
    Nov 28 '13 at 11:38





    Correct. I was only trying to point out what the problem was. Not rewriting the code for him :)

    – Raj
    Nov 28 '13 at 11:38













    Thanks - now it works when i execute it using EXEC. Nut I'm getting an exception when executing it from C# now Exception: System.Data.SqlClient.SqlException: Incorrect syntax near ')'. Do you have any idea what might cause that?

    – Tom
    Nov 28 '13 at 11:40





    Thanks - now it works when i execute it using EXEC. Nut I'm getting an exception when executing it from C# now Exception: System.Data.SqlClient.SqlException: Incorrect syntax near ')'. Do you have any idea what might cause that?

    – Tom
    Nov 28 '13 at 11:40













    never mind -the error was caused by empty (but not null) string parameter: ''

    – Tom
    Nov 28 '13 at 12:00





    never mind -the error was caused by empty (but not null) string parameter: ''

    – Tom
    Nov 28 '13 at 12:00











    0














    You can avoid using dynamic sql by creating a sql function that use a CTE (I found the code below many years ago on sqlservercentral - Amit Gaur) :



    Change the body of your procs with something like this :



    SELECT  p.WPRN AS ID,
    p.Address AS Address,
    p.Address AS Street
    FROM [dbo].[Properties] AS p
    WHERE
    p.WPRN NOT IN ( SELECT item FROM dbo.strToTable(@NotNeededWPRNs, ','))


    Below the sql code that transforms a string into a table :



    CREATE FUNCTION [dbo].[strToTable] 
    (
    @array varchar(max),
    @del char(1)
    )
    RETURNS
    @listTable TABLE
    (
    item int
    )
    AS
    BEGIN

    WITH rep (item,list) AS
    (
    SELECT SUBSTRING(@array,1,CHARINDEX(@del,@array,1) - 1) as item,
    SUBSTRING(@array,CHARINDEX(@del,@array,1) + 1, LEN(@array)) + @del list

    UNION ALL

    SELECT SUBSTRING(list,1,CHARINDEX(@del,list,1) - 1) as item,
    SUBSTRING(list,CHARINDEX(@del,list,1) + 1, LEN(list)) list
    FROM rep
    WHERE LEN(rep.list) > 0
    )
    INSERT INTO @listTable
    SELECT item FROM rep

    RETURN
    END





    share|improve this answer




























      0














      You can avoid using dynamic sql by creating a sql function that use a CTE (I found the code below many years ago on sqlservercentral - Amit Gaur) :



      Change the body of your procs with something like this :



      SELECT  p.WPRN AS ID,
      p.Address AS Address,
      p.Address AS Street
      FROM [dbo].[Properties] AS p
      WHERE
      p.WPRN NOT IN ( SELECT item FROM dbo.strToTable(@NotNeededWPRNs, ','))


      Below the sql code that transforms a string into a table :



      CREATE FUNCTION [dbo].[strToTable] 
      (
      @array varchar(max),
      @del char(1)
      )
      RETURNS
      @listTable TABLE
      (
      item int
      )
      AS
      BEGIN

      WITH rep (item,list) AS
      (
      SELECT SUBSTRING(@array,1,CHARINDEX(@del,@array,1) - 1) as item,
      SUBSTRING(@array,CHARINDEX(@del,@array,1) + 1, LEN(@array)) + @del list

      UNION ALL

      SELECT SUBSTRING(list,1,CHARINDEX(@del,list,1) - 1) as item,
      SUBSTRING(list,CHARINDEX(@del,list,1) + 1, LEN(list)) list
      FROM rep
      WHERE LEN(rep.list) > 0
      )
      INSERT INTO @listTable
      SELECT item FROM rep

      RETURN
      END





      share|improve this answer


























        0












        0








        0







        You can avoid using dynamic sql by creating a sql function that use a CTE (I found the code below many years ago on sqlservercentral - Amit Gaur) :



        Change the body of your procs with something like this :



        SELECT  p.WPRN AS ID,
        p.Address AS Address,
        p.Address AS Street
        FROM [dbo].[Properties] AS p
        WHERE
        p.WPRN NOT IN ( SELECT item FROM dbo.strToTable(@NotNeededWPRNs, ','))


        Below the sql code that transforms a string into a table :



        CREATE FUNCTION [dbo].[strToTable] 
        (
        @array varchar(max),
        @del char(1)
        )
        RETURNS
        @listTable TABLE
        (
        item int
        )
        AS
        BEGIN

        WITH rep (item,list) AS
        (
        SELECT SUBSTRING(@array,1,CHARINDEX(@del,@array,1) - 1) as item,
        SUBSTRING(@array,CHARINDEX(@del,@array,1) + 1, LEN(@array)) + @del list

        UNION ALL

        SELECT SUBSTRING(list,1,CHARINDEX(@del,list,1) - 1) as item,
        SUBSTRING(list,CHARINDEX(@del,list,1) + 1, LEN(list)) list
        FROM rep
        WHERE LEN(rep.list) > 0
        )
        INSERT INTO @listTable
        SELECT item FROM rep

        RETURN
        END





        share|improve this answer













        You can avoid using dynamic sql by creating a sql function that use a CTE (I found the code below many years ago on sqlservercentral - Amit Gaur) :



        Change the body of your procs with something like this :



        SELECT  p.WPRN AS ID,
        p.Address AS Address,
        p.Address AS Street
        FROM [dbo].[Properties] AS p
        WHERE
        p.WPRN NOT IN ( SELECT item FROM dbo.strToTable(@NotNeededWPRNs, ','))


        Below the sql code that transforms a string into a table :



        CREATE FUNCTION [dbo].[strToTable] 
        (
        @array varchar(max),
        @del char(1)
        )
        RETURNS
        @listTable TABLE
        (
        item int
        )
        AS
        BEGIN

        WITH rep (item,list) AS
        (
        SELECT SUBSTRING(@array,1,CHARINDEX(@del,@array,1) - 1) as item,
        SUBSTRING(@array,CHARINDEX(@del,@array,1) + 1, LEN(@array)) + @del list

        UNION ALL

        SELECT SUBSTRING(list,1,CHARINDEX(@del,list,1) - 1) as item,
        SUBSTRING(list,CHARINDEX(@del,list,1) + 1, LEN(list)) list
        FROM rep
        WHERE LEN(rep.list) > 0
        )
        INSERT INTO @listTable
        SELECT item FROM rep

        RETURN
        END






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 28 '13 at 12:01









        user3041160user3041160

        56925




        56925






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f20265023%2fmust-declare-the-table-variable-name-in-stored-procedure%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Bressuire

            Vorschmack

            Quarantine