Использование переменной string в инструкции select * from

#sql #sql-server #select

#sql #sql-сервер #выберите

Вопрос:

Возможно ли что-то подобное?:

 DECLARE @test nvarchar(30) = 'Appt'

SELECT * FROM @test.dbo.tablename with (NOLOCK)
 

или, возможно

 DECLARE @test nvarchar(30) = 'Appt'

SELECT * FROM @test   '.dbo.tablename' with (NOLOCK)    
 

Нет, верно?

Я не собираюсь помещать всю строку в переменную, а затем использовать «EXEC». У меня есть длинные сценарии, которые я хочу просто попытаться заменить, когда это произойдет.

Спасибо.

Комментарии:

1. нет. невозможно. вам нужно создать строку, а затем выполнить ее.

2. Хорошо, это то, что я подумал. Просто надеялся: (

3. Но в чем проблема? Вы можете создать функцию DoQuery(@test) и инкапсулировать EXEC вызов

4. Часто проще взять существующий длинный скрипт, добавить заполнители для всего, что вы хотите заменить, а затем вызвать replace эти строки для заполнения любых значений, чем динамически собирать все это. Похоже, ваша забота в первую очередь связана с простотой разработки / обслуживания. Если у вас есть строка select * from ##dbname##.dbo.tablename with (nolock) , вы можете сделать replace(your_string, '##dbname##, 'Appt') , а затем выполнить это. Если вы просто заменяете имена баз данных, возможно, вам просто нужно sp_MSforeachDB .

5. Возможно, вам потребуется перейти на динамический sql

Ответ №1:

Для этого требуется динамический SQL. По сути, вы создаете строку, которая динамически формирует инструкцию SQL на основе вашего запроса. Затем эта строка выполняется с помощью инструкции EXEC . Базовый пример выглядит так:

 DECLARE @test nvarchar(30) = 'Appt'
DECLARE @sql as varchar(max)
SET @SQL = 'SELECT * FROM'    @test   '.dbo.tablename'   'with (NOLOCK)'
EXEC @SQL
 

Предполагая, что ваше имя таблицы было Appt.dbo.tablename

Я думаю, вы имели в виду:

 SET @SQL = 'SELECT * FROM'    'dbo.'   @test   ' with (NOLOCK)'
 

Комментарии:

1. Ну, проблема в том, что у меня много операторов insert и операторов select. поэтому я не могу поместить их все в переменную.

2.Вы можете написать свое сердце. Вы просто используете SELECT операторы и конкатенацию для создания всего оператора и выполнения в конце. Не забывайте о области видимости. Сложнее создать переменную в динамическом SQL. Также имейте в виду, когда вы выполняете инструкцию: SELECT * FROM ABCD INSERT INTO dbo.Something … Это будет выполняться вместе, даже если нет пробелов.

3. Операторы в вашем вопросе открыты для атак с использованием SQL-инъекций. Всегда используйте QUOTENAME для имен таблиц при построении динамического SQL, чтобы избежать таких атак. Нравится SET @SQL = 'SELECT * FROM' 'dbo.' QUOTENAME(@test) ' with (NOLOCK)' . Также: EXEC (@SQL); (cf msdn.microsoft.com/en-us/library/ms188332.aspx )

Ответ №2:

Логиксолог с хорошим объяснением.

Поскольку Том хочет запустить его для нескольких операторов select, я подумал, что он мог бы сохранить все имена таблиц в столбце и использовать курсор для извлечения значений таблицы. Учитывая, что вы сначала создадите таблицу, такую как:

 CREATE TABLE tableName ( name varchar(20));
 

затем запустите следующий код, как только вы вставили правильные значения в приведенную выше таблицу.

 Declare @table VARCHAR(255)
DECLARE @sql as varchar(max)
SET @SQL = 'SELECT * FROM'    'dbo.'   @table   ' with (NOLOCK)'

DECLARE table_cursor CURSOR FOR 
select distinct([name]) FROM DBname.dbo.tableName
Where [name] is not null

OPEN table_cursor
FETCH Next from table_cursor 
INTO @table
WHILE @@FETCH_STATUS =0
BEGIN

EXEC @SQL

FETCH NEXT FROM table_cursor
INTO @table
END
CLOSE table_cursor
DEALLOCATE table_cursor
 

Курсор вернет имя таблицы для инструкции select . Я думаю, вы могли бы использовать ту же логику для операторов insert.

Комментарии:

1. Большинство администраторов баз данных получили бы изжогу, если бы вы даже упомянули использование курсора для создания динамического SQL. Это может сработать, но его менее легко поддерживать, если вы столкнетесь с проблемой. Сложнее понять, в чем проблема.