#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. Это может сработать, но его менее легко поддерживать, если вы столкнетесь с проблемой. Сложнее понять, в чем проблема.