简体   繁体   中英

Syntax error in sp_executesql

Hi I am trying to run the following SQL which will pull out table names named SourceDestination by iterating through all databases whose name has 'Pull'.

But I am getting an error at the plus sign near '+@db_name+'.sys.tables. I tried N'' on both sides but I can't seem to get it to work.

It gives this error Msg 102, Level 15, State 1, Line 20 Incorrect syntax near '+'.

Need to know where I am wrong. Thanks for the help.

declare db_names cursor for
select name
from master.sys.databases
where name like 'Pull_%'

declare @db_name varchar(50)
declare @table_name varchar(50)
declare @sql nvarchar(100)
DECLARE @ParmDefinition NVARCHAR(500);
open db_names

fetch next from db_names into @db_name

while @@FETCH_STATUS = 0
begin
print @db_name  

    --  set @sql = 'select '+@table_name+'=name from '+@db_name+'.sys.tables'
    --  set @sql = N'select @table_name=name from @db_name.sys.tables where name =    ''SourceDestinations'' '
execute sp_executesql N'select @tbl_name=name from '+@db_name+'.sys.tables where name = ''SourceDestinations'' ', N'@tbl_name varchar(50) OUTPUT', @tbl_name=@table_name OUTPUT
--exec(@sql)o
print @table_name
FETCH NEXT FROM db_names INTO @db_name
    end

    close db_names
    deallocate db_names

You need to build the command string as a seperate step from the sp_executesql call:

set @sql = N'select @tbl_name=name from '+@db_name+'.sys.tables where name = ''SourceDestinations'' '
execute sp_executesql @sql, N'@tbl_name varchar(50) OUTPUT', @tbl_name=@table_name OUTPUT

EDIT The variable may not be being set by the second iteration.
Try adding

SET @table_name = NULL

after

print @table_name

If all you want to do is print the names of the databases the table is in, your script can be much simpler (I fail to see the point of retrieving the table name and printing it every time - what could it be other than SourceDestinations ?):

DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';

SELECT @sql = @sql + 'IF EXISTS (SELECT 1 FROM ' + QUOTENAME(name) 
    + '.sys.tables WHERE name = ''SourceDestinations'')
    PRINT ''' + name + ''';'
FROM sys.databases
WHERE name LIKE 'PULL_%';

EXEC sp_executesql @sql;

I suspect though that you want to do more with this once you've determined where the actual tables live. Ed is absolutely right, you can't concatenate a string to pass into sp_executesql as you are executing it, you must build it beforehand. This is true for all stored procedure calls, eg you can't say:

EXEC sp_who2 'act' + 'ive';

Even though it should be the same thing as:

EXEC sp_who2 'active';

You seem to know this already, at least to some extent, because you declared a @sql variable (though you never use it).

I would change your code to:

DECLARE d CURSOR
  LOCAL STATIC FORWARD_ONLY READ_ONLY 
  FOR SELECT name FROM sys.databases
  WHERE name LIKE 'Pull_%';

DECLARE 
  @db_name NVARCHAR(128),
  @sql     NVARCHAR(MAX);

OPEN d;

FETCH NEXT FROM d INTO @db_name;

WHILE @@FETCH_STATUS = 0
BEGIN
  PRINT @db_name;

  SET @sql = N'IF EXISTS (SELECT 1 FROM ' + QUOTENAME(@db_name)
    + '.sys.tables WHERE name = ''SourceDestinations'')
        PRINT ''' + @db_name + ''';'

  EXEC sp_executesql @sql;

  FETCH NEXT FROM d INTO @db_name;
END

CLOSE d;
DEALLOCATE d;

A couple of key points:

  1. Don't use the default cursor options. In this case it's probably not a huge deal, but it's a bad habit to get into. I highlight one case of performance impact in this blog post: https://sqlblog.org/2011/03/08/t-sql-tuesday-16-this-is-not-the-aggregate-youre-looking-for
  2. Don't use varchar(50) for database/table names. These should be nvarchar(128) according to the rules for identifiers .
  3. Also you should be checking for schema as well. You may get multiple hits for SourceDestinations if someone has inadvertently created one in their own default schema.
  4. Your @sql string should probably be longer than 100 characters. I typically use MAX in these cases because the performance difference isn't worth sitting there wondering whether 255 or 1024 etc. will be enough characters.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM