Ответ 1
exec sp_execsql @Sql
Изменение БД длится только время, чтобы завершить @sql
http://blog.sqlauthority.com/2007/07/02/sql-server-2005-comparison-sp_executesql-vs-executeexec/
Я пытаюсь переключить текущую базу данных с помощью инструкции SQL. Я пробовал следующее, но все попытки не удалось:
Чтобы добавить немного больше деталей.
EDIT: Я хотел бы выполнить несколько вещей в двух отдельных БД, где оба настроены с переменной. Что-то вроде этого:
USE Database1
SELECT * FROM Table1
USE Database2
SELECT * FROM Table2
exec sp_execsql @Sql
Изменение БД длится только время, чтобы завершить @sql
http://blog.sqlauthority.com/2007/07/02/sql-server-2005-comparison-sp_executesql-vs-executeexec/
У меня та же проблема, я преодолел ее с уродливым, но полезным набором GOTO.
Причина, по которой я называю "script runner", прежде чем все, что я хочу скрыть сложность и уродливый подход от любого разработчика, который просто хочет работать с фактическим script. В то же время я могу убедиться, что script выполняется в двух (расширяемых до трех и более) базах данных точно так же.
GOTO ScriptRunner
ScriptExecutes:
--------------------ACTUAL SCRIPT--------------------
-------- Will be executed in DB1 and in DB2 ---------
--TODO: Your script right here
------------------ACTUAL SCRIPT ENDS-----------------
GOTO ScriptReturns
ScriptRunner:
USE DB1
GOTO ScriptExecutes
ScriptReturns:
IF (db_name() = 'DB1')
BEGIN
USE DB2
GOTO ScriptExecutes
END
При таком подходе вы получите, чтобы ваши переменные и SQL Server не волновались, если вам приходилось дважды выполнять инструкцию DECLARE.
Проблема с первым заключается в том, что вы делаете USE 'myDB'
, а не USE myDB
.
вы передаете строку; но USE ищет ясную ссылку.
Последний пример работает для меня.
declare @sql varchar(20)
select @sql = 'USE myDb'
EXEC sp_sqlexec @Sql
-- also works
select @sql = 'USE [myDb]'
EXEC sp_sqlexec @Sql
попробуйте следующее:
DECLARE @Query varchar(1000)
DECLARE @DatabaseName varchar(500)
SET @DatabaseName='xyz'
SET @Query='SELECT * FROM Server.'[email protected]+'.Owner.Table1'
EXEC (@Query)
SET @DatabaseName='abc'
SET @Query='SELECT * FROM Server.'[email protected]+'.Owner.Table2'
EXEC (@Query)
В случае, если кому-то понадобится решение для этого, это одно:
если вы используете динамический оператор USE, все ваши запросы должны быть динамическими, потому что это должно быть все в одном контексте.
Вы можете попробовать с помощью SYNONYM, в основном ALIAS для конкретной таблицы, этот SYNONYM вставляется в таблицу sys.synonyms, поэтому у вас есть доступ к нему из любого контекста.
Посмотрите на это статическое утверждение:
CREATE SYNONYM MASTER_SCHEMACOLUMNS FOR Master.INFORMATION_SCHEMA.COLUMNS
SELECT * FROM MASTER_SCHEMACOLUMNS
Теперь динамический:
DECLARE @SQL VARCHAR(200)
DECLARE @CATALOG VARCHAR(200) = 'Master'
IF EXISTS(SELECT * FROM sys.synonyms s WHERE s.name = 'CURRENT_SCHEMACOLUMNS')
BEGIN
DROP SYNONYM CURRENT_SCHEMACOLUMNS
END
SELECT @SQL = 'CREATE SYNONYM CURRENT_SCHEMACOLUMNS FOR '+ @CATALOG +'.INFORMATION_SCHEMA.COLUMNS';
EXEC sp_sqlexec @SQL
--Your not dynamic Code
SELECT * FROM CURRENT_SCHEMACOLUMNS
Теперь просто измените значение @CATALOG, и вы сможете перечислить одну и ту же таблицу, но из другого каталога.
Если SQLCMD является опцией, он поддерживает переменные сценариев выше и выше того, что может сделать прямой T-SQL. Например: http://msdn.microsoft.com/en-us/library/ms188714.aspx
Просто хотел поблагодарить KM за его ценное решение. Я сам реализовал его, чтобы уменьшить количество строк в запросе shrinkdatabase на SQLServer. Вот мой запрос SQL, если он может помочь кому-либо:
-- Declare the variable to be used
DECLARE @Query varchar (1000)
DECLARE @MyDBN varchar(11);
-- Initializing the @MyDBN variable (possible values : db1, db2, db3, ...)
SET @MyDBN = 'db1';
-- Creating the request to execute
SET @Query='use '+ @MyDBN +'; ALTER DATABASE '+ @MyDBN +' SET RECOVERY SIMPLE WITH NO_WAIT; DBCC SHRINKDATABASE ('+ @MyDBN +', 1, TRUNCATEONLY); ALTER DATABASE '+ @MyDBN +' SET RECOVERY FULL WITH NO_WAIT'
--
EXEC (@Query)
Вы можете сделать это:
Declare @dbName nvarchar(max);
SET @dbName = 'TESTDB';
Declare @SQL nvarchar(max);
select @SQL = 'USE ' + @dbName +'; {can put command(s) here}';
EXEC (@SQL);
{but not here!}
Это означает, что вы можете сделать рекурсивный выбор следующим образом:
Declare @dbName nvarchar(max);
SET @dbName = 'TESTDB';
Declare @SQL nvarchar(max);
SELECT @SQL = 'USE ' + @dbName + '; ' +(Select ... {query here}
For XML Path(''),Type)
.value('text()[1]','nvarchar(max)');
Exec (@SQL)
Используйте exec sp_execsql @Sql
Пример
DECLARE @sql as nvarchar(100)
DECLARE @paraDOB datetime
SET @paraDOB = '1/1/1981'
SET @sql=N'SELECT * FROM EmpMast WHERE DOB >= @paraDOB'
exec sp_executesql @sql,N'@paraDOB datetime',@paraDOB
- Если вы используете переменную для имени базы данных.
- Попробуй что-нибудь вроде этого.
DECLARE @DBName varchar (50)
Установить @DBName = 'Database1'; /* < - Это может быть передано параметром. */
IF (@DBName = 'Database1')
Begin
ИСПОЛЬЗОВАНИЕ [Database1];
SELECT * FROM Таблица1;
End
IF (@DBName = 'Database2')
Begin
USE [Database2];
SELECT * FROM Таблица2;
End
IF (@DBName имеет значение null)
Begin
USE [Database1];
End