Procedure error "Must declare the table" - sql

I have a block code to create a procedure:
CREATE PROCEDURE GetTableinfomation
#table nvarchar(50),
#column nvarchar(50),
#valuedk nvarchar(50)
AS
BEGIN
SELECT *
FROM #table
WHERE #column = #valuedk
END
and I have an error.
Msg 1087, Level 15, State 2, Procedure GetTableinfomation, Line 7
Must declare the table variable "#tenbang".
Why?

You cannot use SQL parameters for table names and columns, only for variables.
You could get around this by using dynamic SQL:
DECLARE #SQL nvarchar(4000)
DECLARE #PARAMS nvarchar(4000)
SET #SQL = 'SELECT * FROM '
+ QUOTENAME(#table,'"') + ' WHERE '
+ QUOTENAME(#column,'"') + '= #param1'
SET #PARAMS = '#param1 nvarchar(50)'
EXEC sp_executesql #SQL, #PARAMS, #param1=#valuedk
See the documentation on sp_executesql for more information:
http://msdn.microsoft.com/en-us/library/ms188001.aspx

Related

Passing Parameters to Create a View in SQL Server using stored procedure - dynamic SQL

I am trying to create views using stored procedure and passing dynamic SQL in SQL Server.
ALTER PROCEDURE sp_businessUnit_totalRequests
(#ViewName AS VARCHAR(50),
#RequiredBU AS VARCHAR(50))
AS
BEGIN
DECLARE #Req_View_Name AS SYSNAME;
DECLARE #sql NVARCHAR(MAX);
SET #Req_View_Name = #ViewName
SET #sql = '
CREATE VIEW [Req_View_Name]
As
BEGIN
Select [Reviewer], Count([Reviewer]) as Total_Requests From [dbo].[reviews_not_sent] where [BU] = #RequiredBU Group By [Reviewer];
END
'
SET #sql = REPLACE(#sql, '[Req_View_Name]', QUOTENAME(#Req_View_Name));
EXEC sp_executesql #sql,
N'#RequiredBU VARCHAR(50)',#RequiredBU=#RequiredBU
END;
EXEC sp_businessUnit_totalRequests 'Annuities_Requests', 'Annuities';
The stored procedure gets created. But when I tried to execute the stored procedure, it says:
Incorrect Syntax near View
This code should work:
ALTER PROCEDURE [dbo].[sp_businessUnit_totalRequests]
(
#ViewName AS VARCHAR(50),
#RequiredBU AS VARCHAR(50)
)
AS
BEGIN
Declare #Req_View_Name AS SYSNAME;
DECLARE #sql NVARCHAR(MAX);
Set #Req_View_Name = #ViewName
set #sql = '
CREATE VIEW [Req_View_Name]
As
Select [Reviewer], Count([Reviewer]) as Total_Requests From [dbo].[reviews_not_sent] where [BU] = ''' + #RequiredBU + ''' Group By [Reviewer];
'
SET #sql = REPLACE(#sql, '[Req_View_Name]', QUOTENAME(#Req_View_Name));
EXEC sp_executesql #sql
END;
This Code works although it suffers from SQL Injection. Parametrized SQL View creation is not possible.

Dynamic SQL "USE [DB]" not worked

I use dynamic sql to create database an tables
this is sql script
DECLARE #DatabaseName VARCHAR(50) = N'test';
EXECUTE ('CREATE DATABASE [' +#DatabaseName+']');
EXECUTE('USE ' + #DatabaseName)
GO
CREATE SCHEMA [Framework]
GO
the error I get
Msg 2714, Level 16, State 6, Line 1
There is already an object named 'Framework' in the database.
Msg 2759, Level 16, State 0, Line 1
CREATE SCHEMA failed due to previous errors
.
this error because EXECUTE('USE ' + #DatabaseName) not work
I try to use
SET #SQL02 = 'USE ['+ convert(nvarchar(50),#DatabaseName) +']; SELECT DB_NAME();'
exec sp_executesql #SQL02
but not work
what I can do?
DECLARE #Query VARCHAR(200);
SET #Query = CONCAT('USE ', QUOTENAME('<MyDatabase>'), '; ', 'select DB_NAME();');
EXECUTE (#Query);
This will return <MyDatabase> as long as you remain within one EXECUTE.
I prefer this form for remote execution:
declare #sql nvarchar(max) = N'select Db_Name()';
<DatabaseName>.sys.sp_executesql #sql;
You can put this logic into a more convenient form by making into a stored procedure:
create procedure dbo.usp_ExecuteSqlCommand (
#databaseName sysname
, #sqlCommand nvarchar(max)
)
as
begin;
set nocount on;
set xact_abort on;
declare #innerStatement nvarchar(max) = #sqlCommand;
declare #outerStatement nvarchar(max);
set #databaseName = QuoteName(ParseName(#databaseName, 1), N'[');
set #outerStatement = #databaseName + N'.sys.sp_executesql #stmt = #innerStatement;';
execute sys.sp_executesql
#stmt = #outerStatement
, #params = N'#innerStatement nvarchar(max)'
, #innerStatement = #innerStatement;
end;
Usage is obvious:
execute dbo.usp_ExecuteSqlCommand
#databaseName = N'master'
, #sqlCommand = N'select Db_Name();';
Try this:(if you use execute, the db context will change only for that execute only)
DECLARE #DatabaseName VARCHAR(50) = N'test';
EXECUTE ('CREATE DATABASE [' +#DatabaseName+']');
use [test]
go
CREATE SCHEMA [Framework]
GO

Input equal (=) in local variable stored procedure

Simple question but wasting time to looking for the answer. I have stored procedure like this
ALTER PROCEDURE [dbo].[sinau]
#id varchar (max)
AS
BEGIN
SET NOCOUNT ON;
declare
#select varchar (4000),
#from varchar (4000),
#where varchar (4000),
#final varchar (4000)
-- Insert statements for procedure here
set #select = 'select *'
set #from = 'from permohonan'
set #where= 'where idpermohonan= '+#id
set #final=#select+#from+#where
execute (#final)
END
After I input parameter and exec that SP, the result is
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '='.
Could you fix this ? Thanks
You need to add spaces:
set #select = 'select * '
set #from = 'from permohonan '
set #where= 'where idpermohonan= '+#id
because without it you get:
select *from permohonanwhere idpermohonan= ...
You should always check your query:
IF #debug = 1
PRINT #select+#from+#where;
But for completness you should not concatenate string and use parametrized sp_executesql:
ALTER PROCEDURE [dbo].[sinau]
#id varchar(MAX)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #query NVARCHAR(MAX);
SET #query =
N'SELECT *
FROM permohonan
WHERE idpermohonan = #id;';
EXEC [dbo].[sp_executesql]
#query,
N'#id VARCHAR(MAX)',
#id;
END
Using Dynamic SQL can be tricky so I strongly recommend to read The Curse and Blessings of Dynamic SQL

How to store values from a dynamic sql into a variable?

I am trying to store next value for the sequence into a variable and the statement is called in a dynamic sql as below.
DECLARE #Sequence VARCHAR(100) = 'IMEIIDLookUP'
DECLARE #NextVal INT
DECLARE #SQL NVARCHAR(4000)
SELECT #SQL = 'SELECT (NEXT VALUE FOR [dbo].' + QUOTENAME(#Sequence) + ')'
SELECT #NextVal = EXEC (#SQL)
SELECT #NextVal
The above query fails with error
Incorrect syntax near the keyword 'EXEC'.
What would be the correct syntax here? Having said that, I cannot avoid using dynamic sql.
Use sp_executesql:
DECLARE #Sequence VARCHAR(100) = 'IMEIIDLookUP';
DECLARE #NextVal INT;
DECLARE #SQL NVARCHAR(4000);
SELECT #SQL = 'SELECT #NextVal = (NEXT VALUE FOR [dbo].' + QUOTENAME(#Sequence) + ')';
exec sp_executesql #SQL, N'#NextVal int output', #NextVal = #NextVal output;
SELECT #NextVal;

Selecting from a table where the name is passed as a variable

I am trying to write a simple stored proc which takes three arguments 'database name one', 'database name two' and 'table name'. The sql will then perform a row count for the defined table in each database and store it.
Working on it piecemeal I have hit the first problem in that you can't do
select * from #tablename
I know you can use dynamic sql with the exec command but this is not ideal as I can't return values.
The following example looks like it should work but doesn't.
declare #tablename as nvarchar(500)
declare #sqlstring as nvarchar(500)
declare #parmdefinition as nvarchar(500)
declare #numrows as bigint
set #tablename = N'dummy_customer'
set #parmdefinition = N'#tablenameIN nvarchar(500), #numrowsOUT as bigint OUTPUT'
select #sqlstring = 'select #numrowsOUT = count(*) from #tablenameIN'
select #sqlstring
exec sp_executesql #sqlstring, #parmdefinition, #tablenameIN = #tablename, #numrowsOUT = #numrows OUTPUT
select #numrows
The error message given is
Msg 1087, Level 16, State 1, Line 1
Must declare the table variable "#tablenameIN".
Currently using SQL Server 2008 SP2.
Edit:
We're doing this because we are doing a migration and the customer wants a report which shows the row count for each table in the source and destination database. As there are many tables being able to use sp_MSForEachTable to call the stored proc seems ideal.
Edit:
The final solution for future reference is
declare #tablename as nvarchar(500)
declare #sqlstring as nvarchar(500)
declare #parmdefinition as nvarchar(500)
declare #numrows as bigint
set #tablename = N'dummy_customers'
set #parmdefinition = N'#tablename nvarchar(500), #numrowsOUT as bigint OUTPUT'
select #sqlstring = 'select #numrowsOUT = count(*) from ' + quotename(#tablename)
exec sp_executesql #sqlstring, #parmdefinition, #tablename = #tablename, #numrowsOUT = #numrows OUTPUT
select #numrows
You'd have to use dynamic sql, and concatenate the table name into the SQL string to then execute via sp_executsql:
select #sqlstring = 'select #numrowsOUT = count(*) from ' + QUOTENAME(#tablename)
EXECUTE sp_executesql ....