Execute query stored in variable in a very specific way - sql

Greetings, I have a problem as follows:
I have an SQL variable declared:
DECLARE #myVariable nvarchar(max)
a third party library set a value for this variable. To simplify, lets say that the value is as follows:
SET #myVariable = 'Select ROWGUID from MySampleTable'
Now, I want to execute the following query:
SELECT ROWGUID FROM myTable WHERE ROWGUID in (exec sp_executesql #myVariable )
However, the above statement does not work because it returns an error telling me that I can't execute stored procedure in that way. I made a workaround and this is what I wrote:
create table #temptable (ID uniqueidentifier null)
if(#myVariable is not null AND #myVariable !='') insert into #temptable exec sp_executesql #myVariable
SELECT ROWGUID FROM myTable WHERE ROWGUID in (select * from #temptable)
DROP TABLE #temptable
This works fine.However I don't think it is a good idea to use temporary table. How can I achieve the same result without necessity of creating temporary tables?
I am using SQL SERVER 2005
UPDATE
Please read what I've written where is the problem:
However, the above statement does not work because it returns an error telling me that I can't execute stored procedure in that way. I made a workaround and this is what I wrote:

Keep it simple
-- Your original declaration
declare #myVariable nvarchar(max)
set #myVariable = 'Select ROWGUID from MySampleTable'
-- Additional code
declare #myQuery nvarchar(max) = 'SELECT ROWGUID FROM myTable WHERE ROWGUID in (' + #myVariable + ')'
exec (#myQuery)

Maybe you could use User Defined Functions instead of stored procedures?

If you are using SQL Server 2005 or 2008, you could use a Common Table Expression instead of creating a temporary table.
Common Table Expressions
Your CTE should look like:
WITH Records (ROWGUID) AS (
SELECT ROWGUID
FROM MySimpleTable
)
Then you can simply use:
SELECT ROWGUID
FROM myTable
WHERE ROWGUID IN (SELECT ROWGUID
FROM Records);
Which potentially means you can drop your Variable.
EDIT
Ok, so CTE is out of the question. But, what about using a Table variable instead of creating a Temporary Table.
DECLARE #myVar nvarchar(max);
DECLARE #table TABLE
(
ROWGUID uniqueidentifier
)
SET #myVar = 'SELECT ROWGUID FROM MySampleTable';
INSERT INTO #table
EXEC sp_executesql #myVar;
SELECT ClientID
FROM myTable
WHERE EXISTS (SELECT ClientID FROM #table);

Related

how to pass table name as parameter to sql table valued function?

I want to pass the table name as a parameter to table_valued function in MS SQL Server
CREATE FUNCTION maxid
(
-- Add the parameters for the function here
#tblname sysname,
#feild nvarchar(max),
)
RETURNS TABLE
AS
RETURN
(
-- Add the SELECT statement with parameter references here
select ISNULL(max(#feild),0)+1 from #tblname
)
You cannot use dynamic SQL in table valued or any other TSQL function. However, the code you provide seems to be used to obtain the next value of some identifier or counter field. The way you want to do it is highly deprecated and leads to concurrency problems.
Indeed, SQL Server can do it using at least two standard methods:
using a sequences
creating an identity column
I have done it but with store procedure
CREATE procedure [dbo].[get_maxid]
#tblname nvarchar(max),
#col nvarchar(max)
as
Begin
declare #sql nvarchar(max);
set #sql='select ISNULL(MAX('+#col+'),0)+1 as id from '+ QUOTENAME( #tblname)
execute sp_executesql #sql
End
Now Execute Store Procedure
exec get_maxid #col='col_name',#tblname='tbl_name'

Avoid using dynamic from clause

How can i avoid using dynamic from clause? Even if i don't know the database name, i prefer to use a static statement, like this:
select *
into #tempTable
from #DBName.Invoices
where InvoiceId = 5.
I got this error: Msg 102, Level 15, State 1, Line 6
Incorrect syntax near '.'.
I need to use select into clause because the column names may be different from each databases;
Thanks!
Unfortunately you will have to use dynamic SQL for this, see below for an example
Declare #DBNAME NVARCHAR(MAX) = 'xxx'
Declare #SQL NVARCHAR(MAX) ='select *
into #tempTable
from ' + #DBName + '.Invoices
where InvoiceId = 5.'
execute sp_executesql #SQL
How can i avoid using dynamic from clause? Even if i don't know the database name, i prefer to use a static statement
SQL wont accept columnnames,tablenames,databasenames as parameters.so unless you you avoid them,you cant avoid dynamic sql..
Change your query to dynamic sql to avoid error..But again you will have a problem with temp tables scope
--This will fail ,because temp table falls under different scope
Declare #sql nvarchar(4000)
set #sql='
select *
into #tempTable
from #DBName.Invoices
where InvoiceId = 5'
---one option is to use global temp tables
declare #dbname varchar(1000)
set #dbname=db_name()
declare #sql nvarchar(4000)
set #sql='select *
into ##tempTable
from '+#DBName+'.dbo.test_Delete '
exec(#sql)
select * from ##temptable
But be carefull with above approach,since above temp table have global scope..
You also can use Openrowset ,some thing like below
select * into #temp from openrowset
('SQLNCLI','Server=yourinstancename;Trusted_Connection=yes;', 'select * form table')

How to use table as variable in stored procedure

There is this query that I keep using over and over:
SELECT column_name, count(column_name) FROM table_name GROUP by column_name ORDER BY COUNT(column_name) DESC
I use this to check which different values there are in a column and how often they occur.
Because I use this query so often and it's repeating the same 4 times: column_name, I was like: why not make a stored procedure:
CREATE PROCEDURE countcv #table_name VARCHAR(50),#column_name VARCHAR(50)
AS
BEGIN
SELECT #column_name,COUNT(#column_name) FROM #table_name GROUP BY #column_name ORDER BY COUNT(#column_name)
END
Here is where I get stuck, I can not manage to get a variable tablename:
Must declare the table variable "#table_name"
I believe that #Julien Vavasseur and #Dark Knight has already addressed to your question.
However, I would like to add here that, Sql Server 2008 introduced Table-Valued Parameter by using which we can pass table type variable to the stored procedures. e.g.
Assuming you have a table by the name tblTest with the below columns
ID INT,
Name VARCHAR(50)
Step 1: Declare a new table User Defined Type
CREATE TYPE tblTestType AS TABLE
(
ID INT,
Name VARCHAR(50)
)
Step 2: Create a STORED PROCEDURE that has tblTestType as parameter
CREATE PROCEDURE countcv
(
#tblName tblTestType readonly
)
AS
INSERT INTO tblTest (ID, Name)
SELECT ID, Name
FROM
#tblName;
Then you can use DataTable (if you are using C#) and pass this data table as a parameter to the Stored Procedure.(you can find an example in the link I provided).
There is no way to do it directly. You need to use dynamicSQL approach. Assuming you pass correct table and column names. Below one should work.
CREATE PROCEDURE countcv #table_name VARCHAR(50),#column_name VARCHAR(50)
AS
BEGIN
declare #SQL nvarchar(max)
set #SQL = 'SELECT '+#column_name+',COUNT('+#column_name+')
FROM '+#table_name+'
GROUP BY '+#column_name+'
ORDER BY COUNT('+#column_name+')'
EXEC sp_executesql #SQL
END
If you want to do something like this, you must use dynamic SQL:
CREATE PROCEDURE countcv #table_name sysname, #column_name sysname
AS
BEGIN
Declare #sql nvarchar(max)
Set #sql = 'SELECT ' + QUOTENAME(#column_name)+', COUNT(' + QUOTENAME(#column_name)+')
FROM ' + QUOTENAME(#table_name)+'
GROUP BY ' + QUOTENAME(#column_name)+' ORDER BY COUNT(' + QUOTENAME(#column_name)+')'
EXEC sp_executesql #sql
END
Use sysname for data type for column and table names (buitin datatype for object names, alias to nvarchar(128))
Use QUOTENAME to add delimeter to column and table names

How to access a database given a string of its name

Alright so say I have code that looks like this.
CREATE Table database_info
(
DBName NVARCHAR (MAX)
);
INSERT INTO database_info (DBName)
VALUES ('db1')
SELECT * FROM database_info
DECLARE #temp nvarchar(MAX)
SET #temp = (SELECT DBName FROM database_info where database_info.DBName = 'db1')
--How I want it to work SELECT * FROM #temp
Is there any kind of operation I could do on this temporary variable to have the string act as a regular SQL command?
Thanks
You may execute a dynamic sql using EXEC. Now, declaring the #sql variable would be quite too much in this case, but it is useful when you are not sure of the length of the statement you will pass to it.
DECLARE #sql AS VARCHAR(MAX)
SET #sql = 'SELECT * FROM ' + #temp
EXEC(#sql)

How to SELECT FROM stored procedure

I have a stored procedure that returns rows:
CREATE PROCEDURE MyProc
AS
BEGIN
SELECT * FROM MyTable
END
My actual procedure is a little more complicated, which is why a stored procedure is necessary.
Is it possible to select the output by calling this procedure?
Something like:
SELECT * FROM (EXEC MyProc) AS TEMP
I need to use SELECT TOP X, ROW_NUMBER, and an additional WHERE clause to page my data, and I don't really want to pass these values as parameters.
You can
create a table variable to hold the
result set from the stored proc and
then
insert the output of the
stored proc into the table variable,
and then
use the table variable
exactly as you would any other
table...
... sql ....
Declare #T Table ([column definitions here])
Insert #T Exec storedProcname params
Select * from #T Where ...
You can use a User-defined function or a view instead of a procedure.
A procedure can return multiple result sets, each with its own schema. It's not suitable for using in a SELECT statement.
You either want a Table-Valued function or insert your EXEC into a temporary table:
INSERT INTO #tab EXEC MyProc
You need to declare a table type which contains the same number of columns your store procedure is returning. Data types of the columns in the table type and the columns returned by the procedures should be same
declare #MyTableType as table
(
FIRSTCOLUMN int
,.....
)
Then you need to insert the result of your stored procedure in your table type you just defined
Insert into #MyTableType
EXEC [dbo].[MyStoredProcedure]
In the end just select from your table type
Select * from #MyTableType
You must read about OPENROWSET and OPENQUERY
SELECT *
INTO #tmp FROM
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc #parameters')
It is not necessary use a temporary table.
This is my solution
SELECT * FROM
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc #parameters')
WHERE somefield = anyvalue
You can copy output from sp to temporaty table.
CREATE TABLE #GetVersionValues
(
[Index] int,
[Name] sysname,
Internal_value int,
Character_Value sysname
)
INSERT #GetVersionValues EXEC master.dbo.xp_msver 'WindowsVersion'
SELECT * FROM #GetVersionValues
drop TABLE #GetVersionValues
Try converting your procedure in to an Inline Function which returns a table as follows:
CREATE FUNCTION MyProc()
RETURNS TABLE AS
RETURN (SELECT * FROM MyTable)
And then you can call it as
SELECT * FROM MyProc()
You also have the option of passing parameters to the function as follows:
CREATE FUNCTION FuncName (#para1 para1_type, #para2 para2_type , ... )
And call it
SELECT * FROM FuncName ( #para1 , #para2 )
You can cheat a little with OPENROWSET :
SELECT ...fieldlist...
FROM OPENROWSET('SQLNCLI', 'connection string', 'name of sp')
WHERE ...
This would still run the entire SP every time, of course.
If 'DATA ACCESS' false,
EXEC sp_serveroption 'SQLSERVERNAME', 'DATA ACCESS', TRUE
after,
SELECT * FROM OPENQUERY(SQLSERVERNAME, 'EXEC DBNAME..MyProc #parameters')
it works.
Use OPENQUERY, and before execute set SET FMTONLY OFF; SET NOCOUNT ON;
Try this sample code:
SELECT top(1)*
FROM
OPENQUERY( [Server], 'SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE [database].[dbo].[storedprocedure] value,value ')
If you get the error 'Server is not configured for DATA ACCESS',
use this:
EXEC sp_serveroption 'YourServer', 'DATA ACCESS', TRUE
For the sake of simplicity and to make it re-runnable, I have used a system StoredProcedure "sp_readerrorlog" to get data:
-----USING Table Variable
DECLARE #tblVar TABLE (
LogDate DATETIME,
ProcessInfo NVARCHAR(MAX),
[Text] NVARCHAR(MAX)
)
INSERT INTO #tblVar Exec sp_readerrorlog
SELECT LogDate as DateOccured, ProcessInfo as pInfo, [Text] as Message FROM #tblVar
-----(OR): Using Temp Table
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp;
CREATE TABLE #temp (
LogDate DATETIME,
ProcessInfo NVARCHAR(55),
Text NVARCHAR(MAX)
)
INSERT INTO #temp EXEC sp_readerrorlog
SELECT * FROM #temp
It sounds like you might just need to use a view. A view allows a query to be represented as a table so it, the view, can be queried.
If your server is called SERVERX for example, this is how I did it...
EXEC sp_serveroption 'SERVERX', 'DATA ACCESS', TRUE;
DECLARE #CMD VARCHAR(1000);
DECLARE #StudentID CHAR(10);
SET #StudentID = 'STUDENT01';
SET #CMD = 'SELECT * FROM OPENQUERY([SERVERX], ''SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE MYDATABASE.dbo.MYSTOREDPROC ' + #StudentID + ''') WHERE SOMEFIELD = SOMEVALUE';
EXEC (#CMD);
To check this worked, I commented out the EXEC() command line and replaced it with SELECT #CMD to review the command before trying to execute it! That was to make sure all the correct number of single-quotes were in the right place. :-)
I hope that helps someone.