use a "temporary table" and "while loop" together in sql - sql

I want to create a table and after that use the table information in a while loop. I had been used 'with' to create the table but my code has error. The code comes below:
declare #i integer
set #i=0;
with cte as
(SELECT ROW_NUMBER()OVER(ORDER BY ItemID) as RowNumber,*,DATEDIFF(day,GETDATE(),AdDateTo)as DaysToExpire
FROM KenticoCMS1.dbo.AD_Advertise inner join KenticoCMS1.dbo.CMS_User
ON KenticoCMS1.dbo.AD_Advertise.ItemCreatedBy = KenticoCMS1.dbo.CMS_User.UserID
WHERE DATEDIFF(day,GETDATE(),AdDateTo) in (SELECT RemainDays FROM KenticoCMS1.dbo.AD_SendEmailForExpire)
AND AdShow=1)
--SELECT * FROM cte
while ( #i<=(select max(RowNumber) from cte))
BEGIN
#i=#i+1;
EXEC msdb.dbo.sp_send_dbmail #profile_name='ExpireAdvertiseEmail',
#recipients= select Email FROM cte where RowNumber=#i , --'mj.yazdani1988#gmail.com',
#subject='Test message',
#body='This is the body of the test message.Congrates Database Mail Received By you Successfully.'
END
GO
and my error:
Msg 156, Level 15, State 1, Line 13
Incorrect syntax near the keyword 'while'.
Msg 156, Level 15, State 1, Line 16
Incorrect syntax near the keyword 'select'.
Msg 102, Level 15, State 1, Line 16
Incorrect syntax near ','.

You cannot use CTE as temporary table. You could create table (or declare table variable), put your data there and do your work:
create table #temp (RowNumber int, Email nvarchar(max)
But so far looks like your code could be changed like this:
declare #Email nvarchar(max)
declare cur cursor local fast_forward for
select
u.Email
from KenticoCMS1.dbo.AD_Advertise as a
inner join KenticoCMS1.dbo.CMS_User as u on u.UserID = a.ItemCreatedBy
where
a.AdShow = 1 and
datediff(day, getdate(), a.AdDateTo) in
(
select t.RemainDays
from KenticoCMS1.dbo.AD_SendEmailForExpire as t
)
open cur
while 1 = 1
begin
fetch cur into #Email
if ##fetch_status <> 0 break
exec msdb.dbo.sp_send_dbmail
#profile_name = 'ExpireAdvertiseEmail',
#recipients = #Email,
#subject = 'Test message',
#body = 'This is the body of the test message.Congrates Database Mail Received By you Successfully.'
end
close cur
deallocate cur
Note table aliases, removing redundant brackets. I think it'll also helps to remove datediff, but have to see your data before.

try this: put this part
while ( #i<=(select max(RowNumber) from cte))
BEGIN
#i=#i+1;
EXEC msdb.dbo.sp_send_dbmail #profile_name='ExpireAdvertiseEmail',
#recipients= (
before
with cte as
and a
)
after
...where RowNumber=#i
for my understanding the cte definition must be followed directly by select (and it can be used in only that one select that follows)
hope it helps...
EDIT: commas obviously part of parameterlist for function

Related

select into a table using a variable as table name dynamic sql not working

I'm trying to execute the code below (I know a lot of people have already asked this question but none of them worked for me). since I have a loop I need to select into multiple new tables with the value of variable name as tables names.
I tried using dynamic sql for the tables name like this:
WHILE ( #Counter <= #len)
begin
DECLARE #name VARCHAR(10),#sql nvarchar(max)
SET #name= (select product from #ProductType where NewPK= #Counter)
set #sql='
select m=DATEPART(month,t2.initial_date),y=DATEPART(year,t2.initial_date) ,t1.user_orders,t1.account_id
into '+#name+'
from (select dbo.sales_info.account_id, count(*) as user_orders
from dbo.sales_info
where dbo.sales_info.product= #name
group by dbo.sales_info.account_id) t1
left join
(select dbo.sales_info.account_id, initial_date= min( dbo.sales_info.start_date)
from dbo.sales_info group by dbo.sales_info.start_date,dbo.sales_info.account_id )t2
on t1.account_id=t2.account_id
order by m,y'
exec (#sql)
SET #Counter = #Counter + 1
end
but I keep getting this error :
Must declare the scalar variable "#name".
Msg 102, Level 15, State 1, Line 10
Incorrect syntax near 't2'.
Msg 137, Level 15, State 2, Line 6
Must declare the scalar variable "#name".
Msg 102, Level 15, State 1, Line 10
Incorrect syntax near 't2'.
The problem is this line of code:
where dbo.sales_info.product = #name
You can use parameters when you execute the code:
exec sp_executesql #sql,
N'#name varchar(10),
#name=#name;

Error in selecting

I am trying to do a select like this -
SELECT COUNT(*)
FROM
(
DECLARE #Emp varchar(100)
SET #Emp = 'Rick'
SELECT *
FROM [Temporary].[dbo].[Employee_Test]
WHERE [Emp_Name] = #Emp
) AS EMPS
I know that I can fix this by putting the DECLARE statements before outer select. But, due to some crappy design, I would prefer to be able to use the inner query as is and then count the number of rows in it. How do I do that ?
The error I get is -
Msg 156, Level 15, State 1, Line 4
Incorrect syntax near the keyword 'DECLARE'.
Msg 102, Level 15, State 1, Line 9
Incorrect syntax near ')'
DECLARE #Emp varchar(100)
SET #Emp = 'Rick';
SELECT COUNT(*)
FROM [Temporary].[dbo].[Employee_Test]
WHERE [Emp_Name] = #Emp
You need to Declare The variable and SET its values before you pass it to the SELECT Statement. You cannot Declare a Variable Inside a Select Statement.
Should you put a semi-colon after the SET statement?
SET #EMP = 'Rick';

crux sql if statement problem

Work on ms-server 2005.In my stored procedure i need to use if statement ,I already try to write but i fail ,My syntax is bellow :
Create Procedure TestProcedure
#Type int
as
SELECT * INTO #temp1 FROM (
if #Type =0
select * from dbo.Manifest
else
select * from dbo.DischargePort
) as b
After execute the above syntax show me error message ,Message is
Msg 156, Level 15, State 1, Procedure TestProcedure, Line 8
Incorrect syntax near the keyword 'if'.
Msg 170, Level 15, State 1, Procedure TestProcedure, Line 14
Line 14: Incorrect syntax near ')'.
How to fix the problem,Thanks in advance.
EDIT Ok, so you can't actually insert into #temptable twice because the compiler does not recocgnize that it uses an if statement, the closest workaround was the following:
IF #Type = 0
BEGIN
exec select * into #temp from dbo.Manifest
END
ELSE
BEGIN
select * into #temp from dbo.DischargePort
END
VERSION 2
DECLARE #Type int = 0
IF #Type = 0
exec ('select * into ##temp from dbo.Manifest')
ELSE
exec ('select * into ##temp from dbo.DischargePort')
SELECT * FROM ##temp
And then remember to drop the table at the end
IF (SELECT object_id('TempDB..##temp')) IS NOT NULL
BEGIN
DROP TABLE ##temp
END
And then you would access ##temp like a normal table. Remember that if you want to add parameters to the dynamic sql use sp_exceutesql to avoid sql injection
You remind to drop #temp at the end. Before table creation,you should check if #temp already exists.
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp (id int)

Syntax error on SQL Server

this could be a stupid syntax error but I just keep reading my procedure but i cannot figure out where are my errors.
Msg 156, Level 15, State 1, Line 41
Incorrect syntax near the keyword
'FOR'.
Here is my code :
alter procedure LockReservation as
DECLARE #edition_id tinyint, #stockid tinyint;
DECLARE #creservation CURSOR FOR select edition_id from reservation where (date_fin - GETUTCDATE()) <= 12;
open creservation;
while ##fetch_status = 0
BEGIN
fetch creservation into #edition_id;
DECLARE #cstock CURSOR
FOR select id from stock where edition_id = #edition_id;
open cstock;
while ##fetch_status = 0
BEGIN
fetch cstock into #stockid;
select stock_id from location where location.stock_id = #stockid and archivage = 0
if ##rowcount = 0
BEGIN
insert into stocks_reserves(id, date_ajout, usure, suppression, edition_id)
Select id, date_ajout, usure, suppression, edition_id
from stock
where stock.id = #stockid
END
END
CLOSE cstock
DEALLOCATE cstock
END
CLOSE creservation
DEALLOCATE creservation
Can somebody help me ?
Don't use the # symbol in your cursor names.
Get rid of the cursor - use a set based solution.
Basically you are doing this:
insert into stocks_reserves
(id, date_ajout, usure, suppression, edition_id)
Select id, date_ajout, usure, suppression, edition_id
from stock
where stock.id in
(
select stock_id
from location
where location.stock_id in
(
select id
from stock
where edition_id in
(
select edition_id
from reservation
where (date_fin - GETUTCDATE()) <= 12
)
)
and archivage = 0
)
You can replace the IN with an exists to process the insert faster.
Better still, do INNER JOIN for possibly the best performance.
Name your cursor creservation instead of #creservation
Drop the # symbol before your cursor name in the DECLARE #cstock CURSOR statement

T-SQL Stored Procedure with While Loop causing Errors in Primary Key Constraints

So I have this MS SQL Stored Procedure:
ALTER PROCEDURE [dbo].[Import_Agent_Client_Bucket_2010]
AS
BEGIN
-- Loop Through Each Agent, Create a Bucket, Add their Clients to the Bucket
DECLARE Agent_Cursor CURSOR FOR
SELECT Agent_GUID, Agent_ID
FROM realforms_2011.dbo.Agent
DECLARE #Agent_GUID uniqueidentifier
DECLARE #Agent_ID int
OPEN Agent_Cursor;
FETCH NEXT FROM Agent_Cursor
INTO #Agent_GUID, #Agent_ID;
WHILE ##FETCH_STATUS = 0
BEGIN
-- Create a bucket for each agent
DECLARE #cbPKTable TABLE (cbPK UNIQUEIDENTIFIER, cbID int)
INSERT INTO realforms_2011.dbo.Client_Bucket ([Description] ) OUTPUT inserted.Client_Bucket_GUID, inserted.Client_Bucket_ID INTO #cbPKTable
SELECT ISNULL(a.First_Name, ' ') + ' ' + ISNULL(a.Last_Name, ' ') + '''s Clients'
FROM realforms_2011.dbo.Agent a
WHERE Agent_GUID = #Agent_GUID
DECLARE #Client_Bucket_GUID uniqueidentifier
SELECT #Client_Bucket_GUID = cbPK FROM #cbPKTable
DECLARE #Client_Bucket_ID int
SELECT #Client_Bucket_ID = cbID FROM #cbPKTable
INSERT INTO realforms_2011.dbo.Agent_Client_Bucket (Agent_GUID, Agent_ID, Client_Bucket_GUID, Client_Bucket_ID)
VALUES (#Agent_GUID, #Agent_ID, #Client_Bucket_GUID, #Client_Bucket_ID)
DECLARE #Client_GUID uniqueidentifier
DECLARE #Client_ID int
-- Get clients from the server (2010)
DECLARE Client_Cursor CURSOR FOR
SELECT C.Client_ID
FROM realforms.dbo.Client C
INNER JOIN realforms.dbo.Agent_Client AC ON AC.Client_ID = C.Client_ID
WHERE AC.Agent_ID = #Agent_ID
ORDER BY C.Client_ID ASC
OPEN Client_Cursor;
FETCH NEXT FROM Client_Cursor
INTO #Client_ID
-- loop through each 2010 client
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #myNewPKTable TABLE (myNewPK UNIQUEIDENTIFIER)
INSERT INTO realforms_2011.dbo.Client (Client_ID,Name,Secondary_Name,[Address],Address_2,City_State_Zip,Phone,Email_Address,Secondary_Email_Address,Create_Date,Last_Change_Date,[Status],File_Under,[Year]) OUTPUT inserted.Client_GUID INTO #myNewPKTable
SELECT c.Client_ID,Name,Secondary_Name,[Address],Address_2,City_State_Zip,Phone,Email_Address,Secondary_Email_Address,Create_Date,Last_Change_Date,[Status],File_Under,2010
FROM realforms.dbo.Client C
INNER JOIN realforms.dbo.Agent_Client AC ON AC.Client_ID = C.Client_ID
WHERE AC.Agent_ID = #Agent_ID AND C.Client_ID = #Client_ID
SELECT #Client_GUID = myNewPK FROM #myNewPKTable
INSERT INTO realforms_2011.dbo.Client_Bucket_Client (Client_Bucket_GUID, Client_GUID, Client_ID, Client_Bucket_ID, [Year])
VALUES (#Client_Bucket_GUID, #Client_GUID, #Client_ID, #Client_Bucket_ID, 2010)
PRINT 'Client Bucket GUID: '
PRINT #Client_Bucket_GUID
PRINT 'Client GUID: '
PRINT #Client_GUID
FETCH NEXT FROM Client_Cursor
INTO #Client_ID;
END;
CLOSE Client_Cursor;
DEALLOCATE Client_Cursor;
FETCH NEXT FROM Agent_Cursor
INTO #Agent_GUID, #Agent_ID;
END;
CLOSE Agent_Cursor;
DEALLOCATE Agent_Cursor;
END
But I get an error message on just a very few of the items, it says
Msg 2627, Level 14, State 1, Procedure
Import_Agent_Client_Bucket_2010, Line
71 Violation of PRIMARY KEY constraint
'Client_Bucket_Client_PK'. Cannot
insert duplicate key in object
'dbo.Client_Bucket_Client'. The
statement has been terminated.
EDIT:
OK, I see what you're doing there, I apologize for missing the OUTPUT statement. Based on that information, it seems like the code could break if a record is not inserted into the Client table in the line right before SELECT #Client_GUID = myNewPK FROM #myNewPKTable. If no record is inserted, you would wind up grabbing the GUID from the previous record and when you go to insert that it would cause the PK violation. You might have to check to make sure that records are being inserted into the Client table.
ORIGINAL ANSWER:
It looks like you're declaring a table:
DECLARE #myNewPKTable TABLE (myNewPK UNIQUEIDENTIFIER)
But then you never put anything into it, so this statement must return null:
SELECT #Client_GUID = myNewPK FROM #myNewPKTable
EDIT:
Why not just do this? I don't see why the table #myNewPKTable is even being created.
SET #Client_GUID = NEWID()
EDIT:
I think the reason you are getting the primary key violation is because #Client_Bucket_GUID is null. At the beginning of the procedure, there is this code:
-- Create a bucket for each agent
DECLARE #cbPKTable TABLE (cbPK UNIQUEIDENTIFIER, cbID int)
...
DECLARE #Client_Bucket_GUID uniqueidentifier
SELECT #Client_Bucket_GUID = cbPK FROM #cbPKTable
After this code is run #Client_Bucket_GUID will always be null. Again, you would have to insert records into #cbPKTable if you wanted to get anything out of it. If you're trying to create a new UNIQUEIDENTIFIER and store it in #Client_Bucket_GUID, just use the NEWID() function.