How can I create multiple views in a stored procedure? - sql

I want to create a temporary stored procedure to create several views; so something like this:
create proc #t1 as
begin
create view v1 as select 1 as x
go
create view v2 as select 2 as x
end
Unfortunately, when I execute this in Microsoft SQL Server 2005, I get a syntax error on the first create view line.
Something like this works:
create proc #t1 as
begin
exec('create view v1 as select 1 as x')
exec('create view v2 as select 2 as x')
end
However, this seems like a terrible way of doing what I want.
So what's wrong with the first attempt, and what's the best way to create multiple views in a stored procedure?

You can't have a go inside a stored procedure. It's not a command in SQL, it's a separator between batches in the SQL Manager, so it will cut the procedure into two batches and cause syntax errors because neither batch is a complete command.

You don't have to write a full blown parser to make this work - all you need to do is what the command line tools/SSMS do - read lines from the file and accumulate them in a (in .Net, it's a stringbuilder, can't remember the equivalent in Java) until you encounter a line which starts with the word GO. Each time you reach that point, send your accumulated buffer to SQL Server, and then empty your buffer and start again.
So long as your current script has GO whenever it's required, the above should work.

This is easy you can achieve this using variable,assign the create view to the #variable then EXEC(#Variable) statements inside the procedure

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.

Can datasource of a report by a big query procedure?

Can the datasource of a google datastudio report come from a bigquery procedure?
If so how?
So far, I've tried calling the procedure from a "Custom Query" like so :
CREATE OR REPLACE PROCEDURE `EDL-DEMO.DatasetDemo.Test`(paramSample1 STRING, paramSample2 INT64)
BEGIN
SELECT *
FROM `EDL-DEMO.DatasetDemo.someView`;
END;
This attempt gave : Error ID: 7b7e7776
Another work around that might be possible would be to use temporary table, but at this point, I will probably step away from procedure instead.
Another option is to use a scheduled query to invoke the procedure on a defined interval, and point the data studio report at the output table(s) generated by the procedure.
This may have been what you were alluding to with the temporary table comment. It's largely a question of the complexity of the procedure; in your example case you could avoid the procedure entirely and do a scheduled CREATE OR REPLACE TABLE ... AS SELECT ... query.

Manipulating data from a stored procedure by saving data into a table

Problem: I have a stored procedure in SQL Server 2012 and I want to put constraints to the output so I only get relevant information.
I am using Execute. The way I see it I have two options:
save the result of the execution into a table, so I can use it for different purposes
put constraints to the variables in Execute so I only get the results I want
The first method is discussed here:
Insert results of a stored procedure into a temporary table .
My code is (due to company information I can't share the whole thing):
create table #mtable ( .... )
Insert into #mtable
Execute [myProcedure]
The error:
An INSERT EXEC statement cannot be nested.
I assume the error is because of the code in the stored procedure. How can I fix that problem without looking into the code for the stored procedure. Is there another way where I can save the content in a table?
My problem can also be solved by proposal #2. Is it possible for me to manipulate the output from the stored procedure with something like:
Execute [myProcedure] where variable1 > 100

How should I select or display the out variable from a stored procedure call?

I'm writing a pretty basic stored procedure that just takes values from the sample DB2 database and computes the standard deviation. I wrote the procedure itself just fine, and I can call it without error. But I can't figure out how to actually display my result or select it in a statement. Everything I try results in a syntax error and I haven't been able to find anyone doing this specific task in my google searches.
This is the gist of my code (snipped for brevity):
CREATE PROCEDURE SAL_STD_DEV
(OUT std_dev real)
LANGUAGE SQL
BEGIN
--do stuff
SET std_dev = 10; --changed for simplicity
END#
CALL SAL_STD_DEV(?)#
All this runs, but just CALL doesn't create any output. What's the syntax to SELECT the out variable? I can't put a DECLARE before the CALL because it's not in a stored procedure, and PRINT doesn't work either.
(# is my terminal character because I'm using ; in the stored procedure)
Edit: Both the create procedure and call statements are made in the same SQL file, the database is connect to through localhost and I'm using DB2 11.1.0.1527 and developing in IBM Data Studio 4.1.2.
From wherever the CALL is being made, that feature might present a Result Set, despite apparently not presenting the result of an OUT parameter. If so, then the stored procedure perhaps could be revised to return the OUT value [instead, or additionally] as a result set, so that the interface that accepts the CALL statement as input, might present that result-set. Regardless:
In a statement processor [e.g. that is not a GUI, but] for which SELECT query output is presented, the following scripted requests should likely suffice:
create variable my_real real
;
call SAL_STD_DEV(my_real)
;
select my_real from sysibm.sysdummy1
;

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.