Adding LOOP to my Stored PROCEDURE - sql

Below is a sample of my stored procedure, can someone help me how I have the following error:
'Msg 22027, Level 15, State 1, Line 0
Usage: EXECUTE xp_fileexist <filename> [, <file_exists INT> OUTPUT]
Msg 245, Level 16, State 1, Procedure TextImpoted01, Line 39
Conversion failed when converting the varchar value 'No' to data type int.'
USE [test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[TextImpoted01]
AS
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(100)
SELECT TOP (1) #SQL = total FROM DealCounter
DECLARE #path NVARCHAR(max)
SET #path = 'c:\temp\TextImpoted'+ #SQL + '.txt'
DECLARE #UpdateSQL NVARCHAR(100)
SET #UpdateSQL = N'UPDATE DealCounter SET total = total + 1'
DECLARE #LOOP NVARCHAR(100)
SELECT TOP (1) #LOOP = total FROM DealCounter
DECLARE #bulk_cmd NVARCHAR(max);
DECLARE #isExists INT
WHILE #SQL <= #LOOP + 1000
BEGIN
SET #path = 'c:\temp\TextImpoted'+ #SQL + '.txt'
exec master.dbo.xp_fileexist #path ,isExists out
SELECT case #isExists
when 1 then 'Yes'
else 'No'
end as isExists
if #isExists = 'No'
BREAK
else
SET #bulk_cmd = 'BULK INSERT TextImpoted FROM '''+ #path + '''
WITH
(
FIELDTERMINATOR = ' + ''';''' + ', ROWTERMINATOR = ' + '''\n'''+ ')';
EXEC sp_executesql #bulk_cmd
EXECUTE sp_executesql #UpdateSQL;
set #SQL = #SQL + 1;
END

First: The output variable from exec master.dbo.xp_fileexist #path ,isExists out
lacks an # sign and should be exec master.dbo.xp_fileexist #path , #isExists out.
Second: The error comes from trying to compare the INT variable #isExists with a char value in the case statement.
The case block is redundant however and could be replaced with:
EXEC master.dbo.xp_fileexist #path ,#isExists OUT
IF (#isExists = 1)
BEGIN
(... your logic here ... )
END

Your problem actually doesn't concerns loops.
You are declaring #isExists as integer here:
DECLARE #isExists INT
And here you're comparing it with varchar value.
if #isExists = 'No'
This produces error you've seen.
Also note this line of code:
exec master.dbo.xp_fileexist #path ,isExists out
It is definitely should be #isExists here and you're missing #

Related

Change all empty strings to NULL using one query with loop. SQL

I have table with columns:
[1959], [1960], [1961] ... [2016];
All these columns are type nvarchar(255), some of these have empty strings ''. I want to change empty strings to NULL. I write query:
DECLARE #empty nvarchar(255);
SET #empty='';
DECLARE #cnt INT = 1959;
WHILE #cnt < 2017
BEGIN
declare #sql nvarchar(1000)
set #sql = 'UPDATE [HDProjEtap1Proba1].[dbo].[TESTGDP] SET [' + CAST(#cnt as nvarchar(255)) + '] = null WHERE ['+ CAST(#cnt as nvarchar(255)) +'] = ' + #empty;
EXEC(#sql);
SET #cnt = #cnt + 1;
END;
But dosn't work. Message error:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '='.
Can you tell me how do it right?
#empty is empty. It doesn't represent the empty string when you concatenate it.
One simple solution is:
SET #empty = '''';
However, you can do the same thing by passing a parameter using sp_executesql. And I like that approach:
declare #cnt INT = 1959;
while #cnt < 2017
begin
declare #sql nvarchar(1000)
set #sql = 'UPDATE [HDProjEtap1Proba1].[dbo].[TESTGDP] SET [' + CAST(#cnt as nvarchar(255)) + '] = null WHERE ['+ CAST(#cnt as nvarchar(255)) +'] = #empty';
exec sp_executesql #sql, N'#empty nvarchar(255)', #empty = '';
set #cnt = #cnt + 1;
end;
Or event:
declare #cnt INT = 1959;
while #cnt < 2017
begin
declare #sql nvarchar(1000)
set #sql = '
UPDATE [HDProjEtap1Proba1].[dbo].[TESTGDP]
SET [#colname] = null
WHERE [#colname] = #empty';
set #sql = replace(#sql, '#colname', cast(#cnt as varchar(255));
exec sp_executesql #sql, N'#empty nvarchar(255)', #empty = '';
set #cnt = #cnt + 1;
end;
Notice that in this version, the SQL statement is easy to read (and hence to modify and debug). It is defined with parameters that are then subsequently replaced.

Dynamic Stored Procedure with View name and Date as parameters

I created a stored procedure which takes a view name and date as parameters and checks if there is record for that date in the view. However, I get the following error
'Operand type clash: date is incompatible with int'.
I am hoping that if the record exists that 1 will be returned else 0 will be returned and I can use that to make a decision in another stored procedure.
The code is listed below
CREATE PROCEDURE [dbo].[usr_RecordExist]
-- Add the parameters for the stored procedure here
#ViewName SYSNAME,
#TransDate Date
--<#Param2, sysname, #p2> <Datatype_For_Param2, , int> = <Default_Value_For_Param2, , 0>
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #DATEVARCHAR nvarchar(4000);
SET #DATEVARCHAR = CONVERT(NVARCHAR, #TransDate, 103);
-- Insert statements for procedure here
DECLARE #SQLCommand NVARCHAR(MAX) =
N'SELECT COUNT(SYMBOL) FROM ' + QUOTENAME(#ViewName) + 'WHERE TRANSDATE = ' + '' + #DATEVARCHAR + '';
EXECUTE [dbo].[sp_executesql]
#sqlCommand;
END
The expression + '' does nothing, use + '''' to add a single quote.
... + '''' + #DATEVARCHAR + '''';
You are using the right tools but in the wrong way, You should not concatenate parameters but pass them as parameters to the system stored procedure sp_executesql as shown below:
CREATE PROCEDURE [dbo].[usr_RecordExist]
#ViewName SYSNAME,
#TransDate Date
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQLCommand NVARCHAR(MAX);
SET #SQLCommand = N'SELECT COUNT(SYMBOL) FROM ' + QUOTENAME(#ViewName)
+ N' WHERE TRANSDATE = #TransDate';
EXECUTE [dbo].[sp_executesql] #sqlCommand
,N'#TransDate Date'
,#TransDate
END
Edit
To get the count in an output parameter you would do the following:
CREATE PROCEDURE [dbo].[usr_RecordExist]
#ViewName SYSNAME,
#TransDate Date,
#Count INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQLCommand NVARCHAR(MAX);
SET #SQLCommand = N'SELECT #Count = COUNT(SYMBOL) FROM ' + QUOTENAME(#ViewName)
+ N' WHERE TRANSDATE = #TransDate';
EXECUTE [dbo].[sp_executesql] #sqlCommand
,N'#TransDate Date, #Count INT OUTPUT'
,#TransDate
,#Count OUTPUT
END
Since you used QUOTENAME() for ViewName why not QUOTENAME(#DATEVARCHAR, '''') or QUOTENAME(#DATEVARCHAR, CHAR(39))
Cosmin got it. Although I also noticed you set #DATEVARCHAR to NVARCHAR(4000) even though convert(NVARCHAR without a length defaults to 30.

Can I use variable in condition statement as value with where condition that test that value

I have the following stored procedure:
ALTER proc [dbo].[insertperoll] #name nvarchar(50) , #snum int , #gnum int
as
DECLARE #value nvarchar(10)
SET #value = 's'+CONVERT(nvarchar(50),#snum)
DECLARE #sqlText nvarchar(1000);
DECLARE #sqlText2 nvarchar(1000);
DECLARE #sqlText3 nvarchar(1000);
declare #g nvarchar(50) = '''g1'''
SET #sqlText = N'SELECT ' + #value + N' FROM dbo.GrideBtable'
SET #sqlText2 = ' where Gnumber = '+#g --here is the problem it error invalid column name -- the #g is value from the table condition
set #sqlText3 = #sqlText+#sqlText2
Exec (#sqlText3) -- here how can i save the result of the exec into varibale
declare #sal nvarchar(50) = #sqlText3
insert employ (name,Snumber,Gnumber,Salary) values(#name,#snum,#gnum,#sal)
QUESTION: How to put in condition variable gets value from the table when i exec it it think that the #g is column but its not its a value from the table to test it so i display one value after the exec the other QUESTION is how to save the result from the exec in variable and then use that value
I'm using SQL Server 2008 (9.0 RTM)
This will be a stored procedure
Thanks in advance
Not sure why you would go through all the loops to insert into the table where you can have a simple insert query like ..
ALTER PROC dbo.[insertperoll] #name nvarchar(50) , #snum int , #gnum int
AS
insert employ (name, Snumber, Gnumber, Salary)
select #name
, #sum
, #gnum
, case when #snum = 1 then s1
when #snum = 2 then s2
when #snum = 3 then s3
when #snum = 4 then s4
end as Salary
from dbo.GrideBtable
where Gnumber = #gnum
If your intent is to have the proc retrieve a salary value from a column determined from the parameter snum and then make an insert into employ using the values passed as parameters and the salary retrieved I think you could refactor your procedure to this:
CREATE proc [dbo].[insertperoll] #name nvarchar(50) , #snum int , #gnum int AS
DECLARE #g NVARCHAR(50) = 'g1'
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'INSERT employ (name,Snumber,Gnumber,Salary) '
SET #sql += N'SELECT ' + QUOTENAME(#name, '''')
SET #sql += N', ' + CAST(#snum AS NVARCHAR(50))
SET #sql += N', ' + CAST(#gnum AS NVARCHAR(50))
SET #sql += N', s' + CAST(#snum AS NVARCHAR(50))
SET #sql += N' FROM dbo.GrideBtable'
SET #sql += N' WHERE Gnumber = ' + QUOTENAME(#g, '''')
EXEC (#sql)
Of course you could add the #g variable to the procedure parameters instead of having it hard coded in the procedure and call it as:
EXEC insertperoll #name='john', #snum=10, #gnum=100, #g='g1'
Sample SQL Fiddle (with some assumptions made about table structure)
You could do this using sp_executesql instead of exec() since this will allow you to use parameters, you can use an output parameter to get the value from the query:
DECLARE #SQL NVARCHAR(MAX) = N'SELECT #val = ' + CONVERT(NVARCHAR(10),#snum) +
N' FROM dbo.GrideBtable WHERE Gnumber = #G1';
DECLARE #val INT; -- NOT SURE OF DATATYPE REQUIRED
EXECUTE sp_executesql #SQL, N'#G1 VARCHAR(20), #val INT OUT', 'G1', #val OUT;

Error coming while creating UDF in Sql Server 2005

Does anyone know what's wrong with this code block.
CREATE FUNCTION [dbo].[udfGetPoint]
(
#UserID INT,
#SqlCountry VARCHAR(1000)
)
RETURNS INT
AS
BEGIN
DECLARE #Points INT
SET #Points = 1
DECLARE #RecordCount sysname
IF #SqlCountry <> ''
BEGIN
EXEC sp_executesql
N'SELECT #DynamicCount = COUNT(UserID) FROM Country WHERE UserID = '+#UserID+' AND LCValues IN (' + #SqlCountry + ')'
,N'#DynamicCount sysname OUTPUT'
,#RecordCount OUTPUT
IF #RecordCount > 0
SET #Points = #Points + 1
END
RETURN #Points
END
If i execute this i got following error:
Msg 102, Level 15, State 1, Procedure udfGetPoint, Line 15
Incorrect syntax near '+'.
You can't concatenate in the parameter setting of a stored procedure.
DECLARE #sql varchar(2000)
SET #SQL = 'SELECT #DynamicCount = COUNT(UserID) FROM Country WHERE UserID = '+#UserID+' AND LCValues IN (' + #SqlCountry + ')'
EXEC sp_executesql
#SQL
,N'#DynamicCount sysname OUTPUT'
,#RecordCount OUTPUT

SQL SERVER 2008 Dynamic query problem

I have a dynamic query which reads like this
Alter PROCEDURE dbo.mySP
-- Add the parameters for the stored procedure here
(
#DBName varchar(50),
#tblName varchar(50)
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
declare #string as varchar(50)
declare #string1 as varchar(50)
set #string1 = '[' + #DBName + ']' + '.[dbo].' + '[' + #tblName + ']'
set #string = 'select * from ' + #string1
exec #string
END
I am calling like this
dbo.mySP 'dbtest1','tblTest'
And I am experiencing an error
"Msg 203, Level 16, State 2, Procedure mySP, Line 27
The name 'select * from [dbtest1].[dbo].[tblTest]' is not a valid identifier."
What is wrong? and How to overcome?
Thanks in advance
It thinks that the contents of #string refer to a stored procedure name. You need to put
EXEC (#string)
or better use the stored procedure sp_executesql
You should also set up some guard code to check that the values you are passing in are the names of real tables and databases. You can query the views in the INFORMATION_SCHEMA to validate the input.
You can read more on safer dynamic SQL on my blog.
Change
exec #string
To
exec(#string)
Here's a working SP I just tested:
CREATE PROCEDURE [dbo].[test]
#DBName varchar(50),
#tblName varchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #string AS VARCHAR(50)
DECLARE #string1 AS VARCHAR(50)
SET #string1 = '[' + #DBName + '].[dbo].[' + #tblName + ']'
SET #string = 'select * from ' + #string1
EXEC(#string)
END
if you use EXEC as:
EXEC #String
it is trying to run a procedure with the name contained within the #String variable. try it out:
create procedure TestProc
as
print 'you called TestProc!'
go
declare #string varchar(20)
set #string='TestProc'
exec #string
if you use EXEC as:
EXEC (#Query)
you run the sql within the #Query variable, try it out:
DECLARE #Query varchar(50)
set #Query='Print ''just ran it!'''
EXEC (#Query)
ALTER PROCEDURE test_sp
-- Add the parameters for the stored procedure here
(
#DBName varchar(50),
#tblName varchar(50)
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
-- Insert statements for procedure here
declare #string as varchar(100)
declare #string1 as varchar(50)
set #string1 = '[' + #DBName + ']' + '.[dbo].' + '[' + #tblName + ']'
Print #string1
set #string = 'select * from' + #string1
Print #string
exec (#string)
SET NOCOUNT OFF
END