T-SQL equivalent of GO - sql

I'm trying to write a T-SQL script to create a database and the corresponding tables. I'm having a problem where the USE statement complains that the database that I just "created" doesn't exist. If I run the script within SQL Server Management Studio so that I can make use of the GO statement, I don't get this issue.
Is there a T-SQL equivalent of GO that I can use to make sure the CREATE DATABASE gets executed before the USE?
I've tried BEGIN/COMMIT TRANSACTION and BEGIN/END but they didn't help.

Is there a T-SQL equivalent of GO that I can use to make sure the CREATE DATABASE gets executed before the USE?
Yes. Dynamic SQL. Each dynamic SQL invocation is a parsed, compiled, and executed as a separate batch.
EG:
exec ('
create database foo
')
exec ('
use foo
create table bar(id int)
')
Note that when used in dynamic SQL use database only change the database context for the dynamic batch. When control returns to the calling batch, the database context is restored.

In C# you should use separate calls to SqlComand for each batch.
High level steps.
Open connection to master.
Create new database (just create database statement).
Instead of USE call SqlConnection.ChangeDatabase(String) Method
Execute remaining batches

Related

Loop Through All SSMS Databases without Recreating Stored Procedure

Background Information:
In Python, I might write something like this if I want to apply the same logic to different values in a list.
database_list = ["db_1", "db_2", "db_3"]
for x in range(0,len(database_list),1):
print("the database name is " + database_list[x])
What I am trying to do:
What I am trying to do in SSMS, is pull a list of DB objects for each database. I created a stored procedure to pull exactly what I want, but I have to run it against each database, so 10 databases mean running it 10 times.
My goal is to do this with a T-SQL query instead of Python.
I tried doing something like this:
exec sp_MSforeachdb 'USE ?; EXEC [dbo].[my_stored_procedure]';
The problem with this is, [dbo].[my_stored_procedure] has to exist in every database I want to do this in.
How can I create the stored procedure in 1 database, but execute it for all databases or a list of databases that I choose?
I know what you are trying to do and if it's what I think (you seem reluctant to actually say!) you can do the following:
In the master database, create your procedure. Normally you wouldn't do this, but in this case you must prefix it sp_
use master
go
create procedure sp_testproc as
select top 10 * from sys.tables
go
Now if you run this, it will return tables from the master database.
If you switch context to another database and exec master.dbo.sp_testproc, it will still return tables from the master database.
In master, run
sys.sp_MS_marksystemobject sp_testproc
Now switch context to a different database and exec master.dbo.sp_testproc
It will return tables from the database you are using.
Try creating your sproc in master and naming it with an sp_ prefix:
USE master
GO
CREATE PROCEDURE sp_sproc_name
AS
BEGIN
...
END
GO
-- You *may* need to mark it as a system object
EXEC sys.sp_MS_marksystemobject sp_sprocname
See: https://nickstips.wordpress.com/2010/10/18/sql-making-a-stored-procedure-available-to-all-databases/
It should then be available in all dbs
Create the stored procedure in the Master database with the sp_ prefix, and use dynamic SQL in the stored procedure so it resolves object names relative to the current database, rather than the database which contains the stored procedure.
EG
use master
go
CREATE OR ALTER PROCEDURE [dbo].[sp_getobjects]
AS
exec ('
select *
from [sys].[objects]
where is_ms_shipped = 0
order by type, name
')
go
use AdventureWorks2017
exec sp_getobjects
#LunchBox - it's your single stored procedure (that you create in one database) that is actually going to need to contain the "exec sp_MSforeach ...." command, and instead of the command to be executed being "EXEC ", it will need to be the actual SQL that you were going to put into the stored proc.
Eg. (inside your single stored procedure)
EXEC sp_MSforeachdb 'USE ?; SELECT * FROM <table>; UPDATE <another table> SET ...';
Think of the stored procedure (that you put into one database) as being no different than your Python code file - if you had actually wanted to achieve the same thing in Python, you would have either needed to create the stored proc in each database, or build the SQL statement string in Python and execute it against each database.
I understand what you thought you might be able to achieve with SQL, but stored procedures really don't work the way you were expecting. Even when you're in the context of a different database, but you run EXEC <different_db>.stored_proc, that stored proc ends up running in the context of the database in which it exists (not your context database).
Now, the only one issue you may come up against is that the standard sp_MSforeachdb stored proc has a limit of 2000 characters for the command that can be executed (although, it does have multiple "command" parameters, this may not be practical if you were planning on running a very large code block, perhaps with variables that carry all the way through). If this is something that might impact what you're intending to do, you could do a search online for "sp_MSforeachdb alternatives" - there seem to be a handful that people have created where the command parameter can contain a larger string.

The real function of the "GO" Statement in SQL?

I heard that GO statement separates the command batches in SQL. And the CREATE transaction should be the only query on a batch.
But when i try:
Create database dbTest
Create table tbSomething(ID int primary key,Name varchar(30))
GO
The output is still SUCCESS.
So how does the GO Statement affect the SQL batches?
GO is used to divide a script into multiple batches.
The word GO is not a sql statement. It is understood by the SQL batch processor (for example SSMS) not by SQL Server.
Simply put, if GO appears on a line on its own, SSMS sends each section delimited by GO as a separate batch. SQL Server never sees the GO lines, only the SQL between them.
Because SQL Server has a syntactic rule that stored procedures must be defined in a batch on their own, you will often find database creation scripts which use GO to delimit the batches so that multiple stored procedures can be created from one script. However it is the client software which understands GO and divides the batches, not SQL server.
'GO' statement in SQL server is to just sends a signal to take the current batch of SQL statements for execution.
To tell in simple words, it works like a delimiter.
It is an indication of end of SQL statement [i.e., 1 batch that needs to be executed].

SSIS Stored Procedure Call

I'm trying to call a simple stored procedure which would return a list of names in normal test format, all in a single line. I'm passing it two parameters, but no matter how i setup the call, either within a OLE DB Source Editor, or within an execute SQL task.
There must be something i'm missing with my SQL statement b/c i keep getting an error.
My SQL command text is
EXEC [dbo].[spGetEmployerIdCSV] ?, ?
The parameters I'm passing are listed exactly as they are declared in the stored procedure, #IDType and #IDNumber, which are mapped to predefined variables.
Every time I try to run it from either task type, I get a
The EXEC SQL construct or statement is not supported.
What is the best way to run a stored procedure within SSIS?
Thank you.
I cannot recreate your issue.
I created a control flow with the proc already in existence.
I have my execute sql task configured as
My parameters tab shows
When I click run, the package goes green.
My initial assumption was that you had signaled that you were using a stored procedure and were erroneously providing the EXEC part. I had done something similar with SSRS but even updating the IsQueryStoredProcedure to True, via Expression, I could not regenerate your error message.
If you are doing something else/different/in addition to what I have shown in the Execute SQL Task, could you amend your question to describe what all functionality the procedure should show.
Did you specify output parameters?
For 2 in / 1 out your SQL code will look like:
EXEC [dbo].[spGetEmployerIdCSV] ?, ?, ? OUTPUT
ResultSet has to be set to none!
I had the same problem.
When you execute the task check the 'Progress' tab; this will give you a 'fully fledged' error details.
In my case I didn't map the parameter which I created in the SQL Task to the actual one in the Stored Procedure.
So, double click the SQL Task, click on Parameter Mapping on the left hand side, then Create the parameters and their respective mappings. Here is a screenshot (in version 2012):
I faced with a similar issue after upgrading to SSDT for VS 2013 (the problem was with lookup element).
Fixed by using this answer:
EXEC ('dbo.MyStoredProcedure')
WITH RESULT SETS
(
(
MyIntegerColumn INT NOT NULL,
MyTextColumn VARCHAR(50) NULL,
MyOtherColumn BIT NULL
)
)
use the same command you use to run the stored procedure in MySQL workbench
call ();
USE this command in Execute SQL Task

Alter All Triggers via T-SQL

Is there a way to update/alter all triggers using Looping T-SQL or a C# Code ?. I need it too update all the triggers in my database because the RAISERROR command has changed in sql server 2012.
You can script out all the triggers into a text file. See:
How to Generate Scripts For All Triggers in Database Using Microsoft SQL Server Management Studio
Then, you can use a text editor to replace the code you need to replace. Then, you can drop your triggers and recreate them. I don't know if your referring to a production database, or one that you are doing development on. I am assuming from your question that you are prepared to make these major changes to your database. Make sure you back up your database first, in any event.
You can get all trigger using
SELECT [name] FROM [sys].[triggers]
and loop through each trigger and execute
EXEC sp_helptext 'TriggerName'
so you will have the create statement with it...

Using table just after creating it: object does not exist

I have a script in T-SQL that goes like this:
create table TableName (...)
SET IDENTITY INSERT TableName ON
And on second line I get error:
Cannot find the object "TableName" because it does not exist or you do not have permissions.
I execute it from Management Studio 2005. When I put "GO" between these two lines, it's working. But what I would like to acomplish is not to use "GO" because I would like to place this code in my application when it will be finished.
So my question is how to make this work without using "GO" so that I can run it programmatically from my C# application.
Without using GO, programmatically, you would need to make 2 separate database calls.
Run the two scripts one after the other - using two calls from your application.
You should only run the second once the first has successfully run anyway, so you could run the first script and on success run the second script. The table has to have been created before you can use it, which is why you need the GO in management studio.
From the BOL: "SQL Server utilities interpret GO as a signal that they should send the current batch of Transact-SQL statements to SQL Server". Therefore, as Jose Basilio already pointed out, you have to make separate database calls.
If this can help, I was faced with the same problem and I had to write a little (very basic) parser to split every single script in a bunch of mini-script which are sent - one at a time - to the database.
something even better than tpdi's temp table is a variable table. they run lightning fast and are dropped automatically once out of scope.
this is how you make one
declare #TableName table (ColumnName int, ColumnName2 nvarchar(50))
then to insert you just do this
insert into #TableName (ColumnName, ColumnName2)
select 1, 'A'
Consider writing a stored proc that creates a temporary table and does whatever it needs to with that. If you create a real table, your app won't be able to run the script more than once, unless it also drops the table -- in which case, you have exactly the functionality of a temp table.