2009-06-24 3 views
21

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

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

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

EDIT: Я хотел бы выполнить несколько вещей в двух отдельных БД, где оба настроены с переменной. Что-то вроде этого:

USE Database1 
SELECT * FROM Table1 

USE Database2 
SELECT * FROM Table2 
+1

После Информация Preet, вам нужно будет поместить все запросы для USE/SELECT в один вызов sp_sqlexec. ИСПОЛЬЗОВАНИЕ не выйдет за пределы звонка. –

+1

Я знаю об этом решении, но он уродлив и нечитабель. Наличие сценария, генерирующего окончательный SQL, также будет вариантом. – Drejc

+0

Извините, я думал, что вы просто искали решение в самом SQL. В SQL вы используете только метод sp_sqlexec; другой вариант - построить SQL-последовательность USE/SELECT извне. Вам все равно придется строить SQL вручную, но, с другой стороны, выбранная среда сценариев/приложений будет легче манипулировать строкой и не выглядеть такой уродливой. –

ответ

9
exec sp_execsql @Sql 

Изменение DB продолжается только в течение времени, чтобы завершить @sql

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

+0

Как сказано в вопросе, это не работает. Например, если я запустил команду SELECT, например: SELECT * FROM Table, выдается ошибка имени недопустимого объекта. – Drejc

+3

выбор должен быть в @SQL - как я сказал, использование используется только на длительность на @sql –

+2

. Это своего рода решение, но бесполезное для моей цели. – Drejc

6

Проблема с бывшим является то, что вы делаете 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 
+1

Предисловие верное с вышесказанным. Хотя USE будет работать для оператора @sql, это не будет постоянным изменением. Наличие параметризованного ИСПОЛЬЗОВАНИЯ также представило бы всевозможные последствия для производительности/компиляции, и я не вижу никакой альтернативной работы. - goodgai 0 секунд назад [удалить этот комментарий] –

-1

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

? Я не понимаю. – Drejc

2

попробовать это:

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) 
+0

Я знаю об этом решении, но это бесполезно для моей цели. – Drejc

-2

- Если вы используете переменную для имени базы данных.
- Попробуйте что-нибудь подобное.

DECLARE @DBName VARCHAR (50)
Набор @DBName = 'Database1'; /* < - Это может быть передано параметром.*/

ЕСЛИ (@DBName = 'Database1')
Begin
      ИСПОЛЬЗОВАНИЯ [Database1];
      SELECT * ОТ Таблица1;
Конец

ЕСЛИ (@DBName = 'database2')
Begin
      ИСПОЛЬЗОВАНИЯ [database2];
      SELECT * ОТ Таблица2;
Конец

IF (@DBName равно нулю)
Начало
      ИСПОЛЬЗОВАНИЯ [Database1];
Конец

9

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

+0

Я знаю, что отвечаю на вопросы с 2009 года, но, надеюсь, кто-то вроде меня найдет здесь что-то, что они могут использовать. – Alpha

+0

Это решение является удивительным, поскольку он НАСТОЯТЕЛЬНО РАБОТАЕТ !!! Я могу просто поместить все мои имена схем в хранимую процедуру с этим, а затем вызвать соответствующий оператор USE, если есть совпадение. Brilliant. (Он даже проверяет, что они находятся в утвержденном наборе имен) – 2014-06-05 17:25:39

+0

Просто заметили это !. Хороший ответ! –

2

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

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

Вы можете попробовать с помощью SYNONYM, в основном ALIAS для конкретной таблицы, этот SYNONYM вставляется в sys.синонимы стола, так что вы имеете доступ к нему из любого контекста

Посмотрите этот статический оператор:

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

1

Просто хотел поблагодарить 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) 
0

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

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

Woops, только что заметил, что это практически то же самое, что было сказано! –

Смежные вопросы