SQL использовать заявление с переменной - PullRequest
25 голосов
/ 24 июня 2009

Я пытаюсь переключить текущую базу данных с помощью оператора SQL. Я пробовал следующее, но все попытки не увенчались успехом:

  1. USE @ DatabaseName
  2. EXEC sp_sqlexec @Sql - где @Sql = 'USE [' + @DatabaseName + ']'

Чтобы добавить немного больше деталей.

РЕДАКТИРОВАТЬ: Я хотел бы выполнить несколько вещей в двух отдельных базах данных, где оба настроены с переменной. Примерно так:

USE Database1
SELECT * FROM Table1

USE Database2
SELECT * FROM Table2

Ответы [ 10 ]

10 голосов
/ 24 июня 2009
   exec sp_execsql @Sql

Смена БД длится только до момента завершения @ sql

http://blog.sqlauthority.com/2007/07/02/sql-server-2005-comparison-sp_executesql-vs-executeexec/

10 голосов
/ 08 ноября 2012

У меня та же проблема, я преодолел ее с помощью уродливого, но полезного набора GOTO.

Причина, по которой я называю «исполнителем сценариев» раньше всего, заключается в том, что я хочу скрыть сложность и безобразный подход от любого разработчика, который просто хочет работать с реальным сценарием. В то же время я могу убедиться, что скрипт выполняется в двух (расширяемых до трех и более) базах точно таким же образом.

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.

9 голосов
/ 24 июня 2009

Проблема с первым заключается в том, что вы делаете 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
3 голосов
/ 27 июля 2016

Просто хотел поблагодарить К.М. за его ценное решение. Я реализовал это сам, чтобы уменьшить количество строк в запросе 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)
2 голосов
/ 28 июня 2014

Я считаю, что кому-то нужно решение для этого, вот одно:

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

2 голосов
/ 24 июня 2009

попробуйте это:

DECLARE @Query         varchar(1000)
DECLARE @DatabaseName  varchar(500)

SET @DatabaseName='xyz'
SET @Query='SELECT * FROM Server.'+@DatabaseName+'.Owner.Table1'
EXEC (@Query)

SET @DatabaseName='abc'
SET @Query='SELECT * FROM Server.'+@DatabaseName+'.Owner.Table2'
EXEC (@Query)
1 голос
/ 12 августа 2009

Если SQLCMD является опцией, он поддерживает скриптовые переменные сверх того, что может делать прямой T-SQL. Например: http://msdn.microsoft.com/en-us/library/ms188714.aspx

0 голосов
/ 22 августа 2016

Вы можете сделать это:

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)
0 голосов
/ 11 августа 2009
-- If you are using a variable for the database name. 
-- Try something like this. 

DECLARE @DBName varchar(50)
Set @DBName = 'Database1'; /*  could be passed in by a parameter. */

IF( @DBName = 'Database1')
Begin
    USE [Database1];
SELECT  FROM Table1;
End

IF( @DBName = 'Database2')
Begin
USE [Database2];
SELECT  FROM Table2;
End

IF( @DBName is null)
Begin
USE [Database1];
End
0 голосов
/ 24 июня 2009

Использование 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
...