how to declare a database - sql

How can I declare a database as when I try the following:
declare #Database1 [$(Database1)]
It states 'Column, parameter, or variable #8: Cannot find data type Database1'.
UPDATE:
So what I am trying to do is create a variable so that it refers to a database, and then I can include that variable in an OUTPUT statement. I'm using visual studio where by I'm using a reference to call the database, but want that reference to be set as a variable:
At the moment I have:
declare #Database1 [$(Database1)]
...
OUTPUT ''+#Database1+'.dbo.Package' 'TableName', 'PackageID', inserted.PackageId,
Core.updXMLFragment ('StatusID', inserted.StatusID, Deleted.StatusID)
INTO #OutputList
Like I said I get an error when I try the above. I know [$(Database1)] is a legit reference to a database, just need to know how to include this into an OUTPUT statement so that when I move it SSMS, it displays it as [Database1] and not an error.
The reason for [$(Database1)] is so that if we ever change the database name, we don't have to change it in our code as we are using this reference to call on the database rather than the database name itself.

One can use sqlcmd Tool to declare the same.
:setvar dbname "TEST"
CREATE DATABASE $(dbname)
GO
ALTER DATABASE $(dbname) SET COMPATIBILITY_LEVEL = 90
GO
ALTER DATABASE $(dbname) SET RECOVERY SIMPLE
GO

try to use Dynamic SQL
DECLARE #Database SYSNAME = 'master'
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = '
USE ' + QUOTENAME(#Database) + '
SELECT DB_NAME()
'
--PRINT #SQL
EXEC sys.sp_executesql #SQL

Related

Incorrect syntax near '#databaseName' when creating a new database [duplicate]

I use the database name in several places in my script, and I want to be able to quickly change it, so I'm looking for something like this:
DECLARE #DBNAME VARCHAR(50)
SET #DBNAME = 'TEST'
CREATE DATABASE #DBNAME
GO
ALTER DATABASE #DBNAME SET COMPATIBILITY_LEVEL = 90
GO
ALTER DATABASE #DBNAME SET RECOVERY SIMPLE
GO
But it doesn't work. So what's the correct way to write this code?
Put the entire script into a template string, with {SERVERNAME} placeholders. Then edit the string using:
SET #SQL_SCRIPT = REPLACE(#TEMPLATE, '{SERVERNAME}', #DBNAME)
and then run it with
EXECUTE (#SQL_SCRIPT)
It's hard to believe that, in the course of three years, nobody noticed that my code doesn't work!
You can't EXEC multiple batches. GO is a batch separator, not a T-SQL statement. It's necessary to build three separate strings, and then to EXEC each one after substitution.
I suppose one could do something "clever" by breaking the single template string into multiple rows by splitting on GO; I've done that in ADO.NET code.
And where did I get the word "SERVERNAME" from?
Here's some code that I just tested (and which works):
DECLARE #DBNAME VARCHAR(255)
SET #DBNAME = 'TestDB'
DECLARE #CREATE_TEMPLATE VARCHAR(MAX)
DECLARE #COMPAT_TEMPLATE VARCHAR(MAX)
DECLARE #RECOVERY_TEMPLATE VARCHAR(MAX)
SET #CREATE_TEMPLATE = 'CREATE DATABASE {DBNAME}'
SET #COMPAT_TEMPLATE='ALTER DATABASE {DBNAME} SET COMPATIBILITY_LEVEL = 90'
SET #RECOVERY_TEMPLATE='ALTER DATABASE {DBNAME} SET RECOVERY SIMPLE'
DECLARE #SQL_SCRIPT VARCHAR(MAX)
SET #SQL_SCRIPT = REPLACE(#CREATE_TEMPLATE, '{DBNAME}', #DBNAME)
EXECUTE (#SQL_SCRIPT)
SET #SQL_SCRIPT = REPLACE(#COMPAT_TEMPLATE, '{DBNAME}', #DBNAME)
EXECUTE (#SQL_SCRIPT)
SET #SQL_SCRIPT = REPLACE(#RECOVERY_TEMPLATE, '{DBNAME}', #DBNAME)
EXECUTE (#SQL_SCRIPT)
You can also use sqlcmd mode for this (enable this on the "Query" menu in Management Studio).
:setvar dbname "TEST"
CREATE DATABASE $(dbname)
GO
ALTER DATABASE $(dbname) SET COMPATIBILITY_LEVEL = 90
GO
ALTER DATABASE $(dbname) SET RECOVERY SIMPLE
GO
EDIT:
Check this MSDN article to set parameters via the SQLCMD tool.
Unfortunately you can't declare database names with a variable in that format.
For what you're trying to accomplish, you're going to need to wrap your statements within an EXEC() statement. So you'd have something like:
DECLARE #Sql varchar(max) ='CREATE DATABASE ' + #DBNAME
Then call
EXECUTE(#Sql) or sp_executesql(#Sql)
to execute the sql string.
You cannot use a variable in a create table statement. The best thing I can suggest is to write the entire query as a string and exec that.
Try something like this:
declare #query varchar(max);
set #query = 'create database TEST...';
exec (#query);

Using a Database Name as a Variable

I'm using this method (How to use a variable for the database name in T-SQL?) to pass a DBname into a variable. This variable is then used with something like this (simplified):
Select column From #DBname
However, when executed...You get, Command(s) completed successfully
Is there a way to adapt this method so that you can see the results of a query? (Not just create or alter a DB)
Something like this should work for you.
[[put code here that sets up #DBname]]
DECLARE #stmt NVARCHAR(MAX) = 'SELECT column FROM ' + #DBname;
EXEC sp_ExecuteSQL #stmt;
Edit: Note that I'm assuming you're using SQL server (you didn't specify in the question).

Why I cannot change database dynamically SQL Server 2008

The following is not working and I am definitely missing the obvious but would be nice if somebody could explain why is not working. I need to change db dynamically.
The print out looks good but does not change db in the SQL Server drop down.
DECLARE #tempSql nvarchar(4000);
DECLARE #FinalSQL nvarchar(4000);
DECLARE #dbName varchar(100);
SET #dbName = 'Pubs';
SET #tempSql = 'SELECT DB_NAME()';
SET #FinalSQL = 'USE ' + #dbName + '; EXEC sp_executesql N''' + #tempSql + '''';
EXEC (#FinalSQL)
If SQLCMD mode is an option for your (within SSMS, for example), you can do this:
:setvar dbname Pubs
USE [$(dbname)]
SELECT DB_NAME()
Or, your original syntax was pretty close. Try this:
DECLARE #db AS NVARCHAR(258);
SET #db = QUOTENAME(N'Pubs');
EXEC(N'USE ' + #db + N'; EXEC(''SELECT DB_NAME();'');');
GO
There is a way to access data from a specific database by using this syntax :
FROM DatabaseName..TableName
maybe you should use a dynamic database name in your scripts, then change it whenever you need
otherwise, take a look at this : http://www.sqlteam.com/article/selecting-data-from-different-databases
Executing the dynamic SQL is done in a scope of its own.
So you do change the current database, as you see, but only within the scope of the dynamic SQL.

How to use a varying database?

I want to use a database which name is stored in a variable. How do I do this?
I first thought this would work but it doesn't:
exec('use '+#db)
That will not change database context
Suggestions anyone?
Unfortunately I don't know of a direct solution to this one. The nearest working version is:
DECLARE #db nvarchar(MAX)
SET #db = 'use DBname'
Exec sp_executesql #db
but this only changes the context for the length of the procedure call. However, more statements can be included in that call to make use of the context:
DECLARE #sql nvarchar(MAX)
SET #sql = 'use DBName SELECT * FROM Table1'
Exec sp_executesql #sql
If you absolutely have to do this using dynamic SQl, I prefer this:
DECLARE #sql nvarchar(MAX)
declare #databasename varchar (20)
Set #databasename = mydatabase
SET #sql = 'SELECT * FROM ' + #databasename + 'dbo.Table1'
Exec sp_executesql #sql
The reason I prefer it is that you can extend it to use multipe datbases in the same query if need be.
I havea a concern that you don't know the datbase name for each table already without resorting to dynamic means. In other words, why can't you write:
SELECT * FROM mydatabase.dbo.Table1
If you have multiple databases with the same table names, likely you have a design problem.
The use statement is only in scope inside the exec block. Therefore you would have to do everything else in the same exec:
exec('use '+ #db + '
--do other stuff'
)
Presumably you know all the possible database names. One (slightly inelligant) way of doing this would be to use a CASE or multiple IF statements to test the variable and hardcode the USE statement for each case.

Fully qualified table names with SP_ExecuteSql to access remote server

Trying to update a table on a linked server (SQL 2000/2005) but my server name will not be known ahead of time. I'm trying this:
DECLARE #Sql NVARCHAR(4000)
DECLARE #ParamDef NVARCHAR(4000)
DECLARE #SERVER_NAME VARCHAR(35)
SET #Sql = 'UPDATE
#server_name_param.dba_sandbox.dbo.SomeTable
SET SomeCol=''data'''
SET #ParamDef = N'#server_name_param VARCHAR(35)'
print #Sql
exec sp_executesql #Sql, #ParamDef, #server_name_param=#SERVER_NAME
Which returns this:
UPDATE
#server_name_param.dba_sandbox.dbo.SomeTable
SET SomeCol='data'
Msg 170, Level 15, State 1, Line 2
Line 2: Incorrect syntax near '.'.
Any ideas? Is there anyway I view the SQL statement that is being executed after the parameters are bound?
You'll have to do this, it can't be parameterised
....
SET #Sql = 'UPDATE ' + #server_name_param + '.dba_sandbox.dbo.SomeTable SET SomeCol=''data'''
....
Edit: There is another way which I used back in my pure DBA days
EXEC sp_setnetname 'AdhocServer', #SERVER_NAME
UPDATE AdhocServer.dba_sandbox.dbo.SomeTable SET SomeCol 'data'
EXEC sp_setnetname 'AdhocServer', 'MeaninglessValue'
sp_setnetname is there from SQL Server 2000 to 2008
Edit2. Permissions:
Try EXECUTE AS LOGIN = 'login_name' , where login_name is a superuser
I've not really used this (I use "AS USER" for testing), so not sure of the finer points...
Edit 3: for concurrency, consider using sp_getapplock and a stored procedure, or some other concurrency control mechanism.
You cannot do this with parameters directly - you would have to use dynamic SQL, or send the server name as a parameter to an SP that does dynamic SQL:
DECLARE #template NVARCHAR(4000)
DECLARE #Sql NVARCHAR(4000)
DECLARE #SERVER_NAME VARCHAR(35)
SET #template = 'UPDATE {#server_name_param}.dba_sandbox.dbo.SomeTable SET SomeCol=''data'''
SET #sql = REPLACE(#template, '{#server_name_param}', #SERVER_NAME)
print #Sql
exec sp_executesql #Sql -- OR EXEC ( #sql )
I like gbn's trick. I didn't know that one and I'm gonna have to research that some more.
Since I didn't know that trick, I've had to use dynamic sql in similar situations in the past (like what Cade posted). When that happens I would normally query an information schema view to make sure the parameter value is a real database object before building the query. That way I'm sure it's not an injection attempt.