Use database dynamically - sql-server-2005

This execution is giving me the following error:
Msg 102, Level 15, State 1, Line 5
Incorrect syntax near 'go'.
Msg 111, Level 15, State 1, Line 11
'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.
If i remove the "GO" it gives me just the second one.
Any hints of what am I missing?
declare #dbname varchar(500)
set #dbname='master'
Exec ('
Use ' + #dbname + '
go
create PROCEDURE [dbo].[krijo_database] #dbname nvarchar(2000), #Direktoria varchar(4000)
AS
BEGIN
declare #stringu nvarchar(100)
set #stringu =
''CREATE DATABASE '' + #dbname
exec (#stringu)
End
')
Answer
declare #dbname varchar(500)
set #dbname='kontabel'
Exec(
'Use ' + #dbname +'
Exec (''
create PROCEDURE [dbo].[krijo_database] #dbname nvarchar(2000), #Direktoria varchar(4000)
AS
BEGIN
declare #stringu nvarchar(100)
set #stringu =
''''create DATABASE '''' + #dbname
exec (#stringu)
End
'')
')
Actually I tried like this and it worked but I had to change quotes.
The real procedure that I would like to use is more than 50000 lines and I can't go and manually change the quotes to everything.
Is there a better way?

Two issues:
Using "GO" is incorrect... there is no SQL keyword called "GO"... that's just a hack that SQL Server Management Studio is performing for you.
You need to the CREATE PROCEDURE command in it's own context... simple.
Here's the slight modification to your script:
declare #dbname varchar(500)
set #dbname='master'
Exec ('
Use ' + #dbname + '
EXECUTE(''create PROCEDURE [dbo].[krijo_database] #dbname nvarchar(2000), #Direktoria varchar(4000)
AS
BEGIN
declare #stringu nvarchar(100)
set #stringu =
''''CREATE DATABASE '''' + #dbname
exec (#stringu)
End'')
')
So the answer is to put another "EXECUTE" command inside the first EXECUTE command. I do this all the time, a lot of times in an "sp_msforeachdb". You can nest those bad boys as long as you want.

Sometime ago I had code which was updating database structure based on scripts.
I end up with split file by 'go' and execute separately each fragment. Can you try this?
So, first exec use statement, and than exec createprocedure.
Be sure to verify that it is created in proper database

My mistake, I didn't notice something.
maybe it's the Exec inside the Exec that's causing the error?
or because your'e assigning a nvarchar(2000) to a nvarchar(100)
"Msg 102, Level 15, State 1, Line 5 Incorrect syntax near 'go'. Msg 111, Level 15, State 1, Line 11 'CREATE/ALTER PROCEDURE' must be the first statement in a query batch. " If i remove the "GO" it gives me just the second one.
try this without any use or go: create PROCEDURE '+#dbname+'.[dbo].[krijo_database] #dbname nvarchar(2000)

You can't use GO like that
It isn't a SQL command
It tells SSMS to split the batch
If you remove it, then you'll get "first in batch" error which is expected
In this case, why not just do this...
Use master
GO
create PROCEDURE [dbo].[krijo_database] #dbname nvarchar(2000), #Direktoria varchar(4000)
AS
BEGIN
declare #stringu nvarchar(100)
set #stringu = 'CREATE DATABASE ' + #dbname
exec (#stringu)
End
GO
Why do need dynamic SQL to create a stored procedure?

USE master
GO
CREATE PROCEDURE dbo.create_database #name nvarchar(100)
AS
DECLARE #sql nvarchar(100)
SET #sql = 'CREATE DATABASE ' + QUOTENAME(#name)
EXEC (#sql)
GO

What you're after can't be done I don't think.
See this article for reference

The Real procedure that i would like to use it is a very big one, more dhan 50000 lines and i can't go on an changing the quotes to everything
Microsoft SQL Server has a maximum length of varchar of 8000 characters.
http://www.databasejournal.com/features/mssql/article.php/3788256/Data-Types-in-SQL-Server-2008.htm

you should create stored procedure with that portion with variable.

I used SQl DMO!
Great feature both for 32 and 64 bit,compatible with both SQL express and server!

Related

Create trigger in CREATE DATABASE stored procedure

We have a stored procedure that creates a database for each of our customers. This stored procedure runs in the context of master. A database name is passed in as a parameter to the stored procedure.
I am trying to modify the stored procedure to add a trigger to a table. I understand the stored procedure must switch to the new database to create triggers, so have appended the following to the stored procedure:
SET #str = ('USE ' + QUOTENAME (#db_name) + ' GO
CREATE TRIGGER ...')
EXEC (#str);
I get the error
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near 'GO'.
Msg 111, Level 15, State 1, Line 4
'CREATE TRIGGER' must be the first statement in a query batch.
Now I assume the second error is a consequence of the first, but I am blowed if I can work out how to switch databases in the stored procedure in order to create the triggers.
We are using SQL Server 2019. How do I create triggers in a create database stored procedure?
Another approach is to execute statement one after another.
DECLARE #str VARCHAR(MAX)
DECLARE #db_name SYSNAME = 'YourDBName'
SET #str = 'USE ' + QUOTENAME (#db_name)
EXEC (#str)
SET #str = 'CREATE TRIGGER ...'
exec (#str);
For completeness, as mentioned by #DaleK, adding the approach mentioned by Aaron Bertnard in the Stackexchange link
DECLARE #str VARCHAR(MAX)
DECLARE #db_name SYSNAME = 'master'
SET #str = 'EXEC '+ #db_name + '..sp_executesql #stmt=N''CREATE PROCEDURE usp_test AS SELECT 1;'''
exec (#str);

OPENQUERY(SERVERNAME, STOREDPROCEDURE) Syntax error

This is my code
DECLARE #stringvariable nvarchar(200) = 'Hello';
DECLARE #sql nvarchar(2000) = SELECT * INTO ##global FROM OPENQUERY(DB1, ''EXEC GETCASE ''' + #stringvariable + ''''')'
Printing #sql returns a correctly formatted query, however SQL Server doesn't like #stringvariable and returns an error
Msg 102, Level 15, State 1, Line 11
Incorrect syntax near 'Hello'.
Here is what the outputted query looks like
SELECT * INTO ##global FROM OPENQUERY(DB1, 'EXEC GETCASE 'Hello'')
How can I avoid this error? It seems like because my stored procedure takes a string parameter, it's throwing off the query. I've read that OPENQUERY does not support variables, but I've parameter the variable so it should work?
Appreciate your help!
The stored procedure exists in a database and a schema. You need to supply those. Supposing database db_name and schema schema_name:
DECLARE #stringvariable nvarchar(200) = 'Hello';
SET #stringvariable=REPLACE(#stringvariable,'''',''''''''''); -- doubly doubled single quotes for the dynamic statement
DECLARE #sql nvarchar(2000) = 'SELECT * INTO ##global FROM OPENQUERY(DB1, ''SET FMTONLY OFF;EXEC db_name.schema_name.GETCASE ''''' + #stringvariable + ''''''')';
I've also made sure single quotes are properly escaped in the #stringvariable.
It's also likely you need to start the query with SET FMTONLY OFF; so I've added that.
Update: To test this I created following simple procedure on a linked server local_server in database TEST_TT
CREATE PROCEDURE [dbo].[tst]
#i VARCHAR(128)
AS
SELECT #i AS field;
I then ran the following:
DECLARE #var VARCHAR(128)='TT.';
SET #var=REPLACE(#var,'''',''''''''''); -- doubly doubled single quotes for the dynamic statement
DECLARE #stmt VARCHAR(4000)='SELECT * INTO ##tt FROM OPENQUERY(local_server,''SET FMTONLY OFF;EXEC TEST_TT.dbo.tst '''''+#var+''''''');';
EXEC (#stmt);
SELECT * FROM ##tt;
DROP TABLE ##tt;
And I received the results. I count 7 (!!) single quotes at the end of the query... yuck! Updated original part with the same number of quotes.

Error with OPENQUERY

I have this proble.
I should to call a Function at a LinkedServer database. So this database not show me a Function.
For this I use this code:
BEGIN
DECLARE #TSQL varchar(8000)
DECLARE #Data as DATE
SET #Data = GETDATE()
SET #TSQL = 'SELECT PIPPO FROM OPENQUERY([SQLIMELTC\IMELTCPROD],''SELECT [FlexNet].[dbo].[AF_GetUTCToLocal] (''''' +CAST(#Data AS NVARCHAR(100))+ ''''') AS PIPPO'' )'
EXEC #TSQL
END
I have this error:
Msg 203, Level 16, State 2, Line 10
The name 'SELECT PIPPO FROM OPENQUERY([SQLIMELTC\IMELTCPROD],'SELECT [FlexNet].[dbo].[AF_GetUTCToLocal] (''2015-01-08'') AS PIPPO' )' is not a valid identifier.
But, if I try to use this code before the instruction
EXEC #TSQL
and use it:
SELECT #TSQL
And after the execute I select in output box the result and execute it, it works.
What is my problem?
Look at the EXECUTE (Transact-SQL) syntax. When you use the variable you should use it in brackets.
Try this:
EXEC (#TSQL)
You need to put parenthesis around #TSQL, e.g.
EXEC (#TSQL);
EXEC without parenthesis is for executing stored procedures. e.g.
DECLARE #TSQL VARCHAR(8000) = 'sp_lock';
EXEC #TSQL;
Will execute the stored procedure sp_lock
Better still use sp_executesql, thus avoiding ambiguity:
EXECUTE sp_executesql #TSQL;

Cursor to execute t-sql create view statement

I'm looking to migrate several SQL views from one database to another. Both databases definitions are identical, so I should not have to worry about compatibility issues. I will have to perform this task on several client systems so I am looking to automate it instead of using the 'Script View As' option and manually duplicating each view.
I am brand new to cursors, so I apologize if this is a terribly simple request but I have tried several approaches and gotten nowhere. My searches of this site and others have been similarly fruitless. This is what I have come up with so far:
declare #sql nvarchar(max)
declare #view nvarchar(max)
declare #dbname nvarchar(30)
set #dbname = 'DatabaseName'
DECLARE cCursor CURSOR LOCAL FOR
SELECT VIEW_DEFINITION
from INFORMATION_SCHEMA.views
where TABLE_NAME like '%MyCriteria%'
OPEN cCursor
FETCH NEXT FROM cCursor into #view
WHILE ##FETCH_STATUS = 0
BEGIN
set #sql = 'USE ' + #dbname + ' GO ' + #view
execute #sql
FETCH NEXT FROM cCursor into #view
END
close cCursor
deallocate cCursor
I am getting an error message upon execution that says:
Msg 203, Level 16, State 2, Line 17
The name 'USE DATA14 GO CREATE VIEW
.... is not a valid identifier.
where the .... represents the create view statement I fetched from Information schema.
Any ideas what I'm doing wrong?
Thanks in advance.
EDIT:
I tried another approach that does not rely on cursors and I believe I am closer, but I am still getting errors that have me baffled:
use SourceDB
go
declare #sql nvarchar(max)
set #sql = N''
select #sql = #sql + 'USE DestDB' + CHAR(13) + CHAR(10) + 'GO' + CHAR(13) + CHAR(10) + s.definition + CHAR(13) + CHAR(10) + 'GO' + CHAR(13) + CHAR(10)
from sys.sql_modules as s
inner join sys.objects as o
on s.object_id = o.object_id
where o.type_desc = 'VIEW'
and s.definition like '%MyCriteria%'
exec data14..sp_executesql #sql
--select #sql
The text of the error message is:
Msg 102, Level 15, State 1, Line 2
Incorrect syntax near 'GO'.
Msg 111, Level 15, State 1, Line 3
'CREATE VIEW' must be the first statement in a query batch.
Msg 102, Level 15, State 1, Line 22
Incorrect syntax near 'GO'......
and so on and so forth for each view in the list
Another option is to use Powershell. There are many ways to do it, I personally like to make a file for each script, and I am making an assumption that the views do not already exist in the new database. So this probably will not work verbatim, but should get you pointed in the right direction.
Create an export folder on the server (C:\Temp\Views)
Open the source server in the object explorer.
Navigate to the source database (/Databases/{DatabaseName})
Right click on 'Views' and select 'Start Powershell'
Run the following command which will create a file for each view:
ls | ? { $_.name -match "MyCriteria" } | %{ $_.scriptheader(0) + $_.textbody > "C:\temp\views\$($_.Schema).$($_.name).sql" }
Import the scripts into another database with
ls "C:\temp\views" | %{ invoke-sqlcmd -inputfile $_.fullname -database "DatabaseName" }
To achieve what you're looking for, you have to nest your dynamic SQL within dynamic SQL...
DECLARE #sql nvarchar(max)
DECLARE #dbname nvarchar(30)
SET #dbname = 'DatabaseName'
SET #sql = '';
SELECT #sql = #sql + '
EXEC ' + #dbname + '.sys.sp_executesql N''' + REPLACE(VIEW_DEFINITION, '''', '''''') + ''''
FROM INFORMATION_SCHEMA.views
WHERE TABLE_NAME like '%table%'
EXEC (#sql);
There is a catch though.
The double dynamic sql needs to be double escaped. Hence the REPLACE above.
By the way... The correct syntax for executing dynamic SQL is EXEC (#SQL) -- Note the brackets
Without the brackets, you're telling the server to execute a procedure. Hence the reason for your first error
Hope that helps

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.