I've written this SQL Server stored procedure that inserts records into another table based on the order frequency of customers in another table. It assigns a rank to each customer based on their order frequency. When I create the procedure and execute it for the first time, it works fine and inserts the correct records into the table. But when I clear the table and try to execute the procedure again, no records are added. I have to delete the procedure, restart SSMS, and create the procedure again for it to work correctly again.
Here is the procedure:
create procedure TopKCustomer (#CustRank decimal(11,0))
as
declare CustCursor cursor local for
select o.CustomerID,c.CustomerName,c.CustomerPostalCode,
count(o.CustomerID) as 'Order Frequency'
from (Customer_T c join Order_T o on c.CustomerID=o.CustomerID)
group by o.CustomerID,c.CustomerName,c.CustomerPostalCode
order by [Order Frequency] desc;
declare #PrevOrderFreq float;
declare #CurrOrderFreq float;
declare #CurrRank decimal(11,0);
declare #CurrCustID decimal(11,0);
declare #CurrCustName varchar(25);
declare #CurrCustPostCode varchar(10);
begin
set #PrevOrderFreq = 0;
set #CurrOrderFreq = 0;
set #CurrRank = 0;
set #CurrCustID = 0;
set #CurrCustName = '';
set #CurrCustPostCode = '';
open CustCursor;
while ##FETCH_STATUS = 0
begin
fetch next from CustCursor into #CurrCustID, #CurrCustName, #CurrCustPostCode, #CurrOrderFreq;
if #CurrOrderFreq <> #PrevOrderFreq
begin
set #CurrRank = (#CurrRank + 1);
if #CurrRank > #CustRank
begin
break;
end
end
insert into TopKCustomer_T
values (#CurrCustID, #CurrCustName, #CurrCustPostCode, #CurrRank, getdate());
set #PrevOrderFreq = #CurrOrderFreq;
end
close CustCursor;
deallocate CustCursor;
end
Here are the tables I'm working with:
Customer_T (CustomerID, CustomerName, CustomerAddress, CustomerCity, CustomerState, CustomerPostalCode)
Order_T (OrderID, CustomerID, OrderDate)
TopKCustomer (CustomerID, CustomerName, CustomerPostalCode, CRank, RankGenerateDate)
I think the problem is
while ##FETCH_STATUS = 0
This will be result of the previous fetch (in other words the fetch from the previous execution of your stored procedure, not what you want).
The usual way I wrote cursor loops is
while 1 =1
begin
fetch next from c into ...
if ##fetch_status != 0 break
...
end
There's no sample data or table structure so I don't know what your data looks like. Below is what I think you want. The inner query count the order per customer. The outer query rank them.
SELECT *
, DENSE_RANK() OVER(PARTITION BY CustomerID ORDER BY OrderFrequency) AS Rnk
FROM (
SELECT *
, COUNT(*) OVER (PARTITION BY o.CustomerID) AS OrderFrequency
FROM Customer_T c
JOIN Order_T o ON c.CustomerID = o.CustomerID
) a
I'm writing tsqlt against a proc that can be run against various parameter values. I initially built a proc that populates fake tables - and then 1 tsqlt test per possible value (ended up with 35 tests and they each worked).
What I would like to do is reduce these into 1 test (since they are all really testing the same functionality - just for different values). I thought I could do this with a cursor like so:
---- Declare Sproc Variables
DECLARE #ReviewId INT;
DECLARE #SourceId INT = 1;
CREATE TABLE #Present
(
SubmissionReviewId INT ,
username VARCHAR(50)
);
CREATE TABLE #Expected
(
SubmissionReviewId INT ,
username VARCHAR(50)
);
--Create Cursor to loop through each active value
DECLARE review_id CURSOR
FOR
SELECT ReviewId
FROM reftype.Rev
WHERE IsActive = 1;
OPEN review_id;
FETCH NEXT FROM review_id
INTO #ReviewId;
WHILE ##FETCH_STATUS = 0
BEGIN
--Setup Fake Data according to the specified test condition
EXEC ut_DataSetupProc #ReviewId = #ReviewId;
-- Run set cutover Sproc
EXEC Procbeing Tested #ReviewId = #ReviewId,
#SourceId = 1, #Username = 'blah';
-- Confirm appropriate review is present in Submission Review Active
DELETE FROM #Present;
DELETE FROM #Expected;
INSERT INTO #Present
SELECT SubmissionReviewId ,
LastModifiedBy
FROM review.SubmissionReviewActive
ORDER BY SubmissionReviewId ,
LastModifiedBy;
/**********************Create table holding expected values***************************/
INSERT INTO #Expected
--This confirms active reviews that belong to other sections/sources remain unaffected
SELECT SubmissionReviewId ,
LastModifiedBy
FROM review.SubmissionReviewActive
WHERE ( ReviewId != #ReviewId )
OR ( SourceId != #SourceId )
UNION
SELECT sra.SubmissionReviewId ,
sra.LastModifiedBy
FROM review.SubmissionReviewActive sra
JOIN review.SubmissionReviewFutureActive srfa ON srfa.IssuerId = sra.IssuerId
AND srfa.ReviewId = sra.ReviewId
AND srfa.Version < sra.Version
WHERE sra.ReviewId = #ReviewId
AND sra.SourceId = #SourceId
UNION
SELECT srfa.SubmissionReviewId ,
'jmarina' AS LastModifiedBy
FROM review.SubmissionReviewFutureActive srfa
JOIN review.SubmissionReviewActive sra ON srfa.IssuerId = sra.IssuerId
AND srfa.ReviewId = sra.ReviewId
AND srfa.Version > sra.Version
WHERE sra.ReviewId = #ReviewId
AND srfa.SourceId = #SourceId
UNION
SELECT srfa.SubmissionReviewId ,
'blah' AS LastModifiedBy
FROM review.SubmissionReviewFutureActive srfa
WHERE srfa.ReviewId = #ReviewId
AND srfa.SourceId = #SourceId
AND srfa.IssuerId NOT IN (
SELECT IssuerId
FROM review.SubmissionReviewActive
WHERE ReviewId = #ReviewId
AND SourceId = #SourceId )
UNION
SELECT sra.SubmissionReviewId ,
sra.LastModifiedBy
FROM review.SubmissionReviewActive sra
WHERE sra.ReviewId = #ReviewId
AND sra.SourceId = #SourceId
AND IssuerId NOT IN (
SELECT IssuerId
FROM review.SubmissionReviewFutureActive
WHERE ReviewId = #ReviewId
AND SourceId = #SourceId )
ORDER BY SubmissionReviewId ,
LastModifiedBy;
/*************************************************************/
EXEC tSQLt.AssertEqualsTable #Expected = '#Expected',
#Actual = '#Present', #Message = N'', -- nvarchar(max)
#FailMsg = N'Active Status is not a match'; -- nvarchar(max)
FETCH NEXT FROM review_id
INTO #ReviewId;
END;
CLOSE review_id;
DEALLOCATE review_id;
DROP TABLE #Expected;
DROP TABLE #Present;
END;
However, running this using
EXEC proc name #ReviewId = #ReviewId;
yields a message saying no tests were run. How can I sue a cursor to reduce my number of tests? Or is there another approach I should consider?
I'd suggest you write something called a parameterized test.
tSQLt does not (yet) have native support for that, but there is an easy workaround:
You start by writing one of your tests normally. But instead of hardcoding the pertinent values, you make them parameters of the procedure. (For data sets, you can use table parameters.)
You also name that procedure something that doesn't start with "test" (but lives in the same schema).
Then you write one real test per actual case, each one consisting of one line: the execution of your parameterized procedure.
That will lead to tests that are a lot easier to understand than your current approach. And additionally, if one of them fails, you immediately know which.
As a side note: You always want to hardcode your expected results. Your current code is way complex. You want to minimize things that can go wrong in the test itself. Really, your goal should be tests that can be understood with one glance.
In the end I achieved the end goal in a couple of steps:
1. Move the assert statement outside of the cursor
2. Created 'cased' temp table with pass/fail records
INSERT INTO #ActualAssert
SELECT p.SubmissionReviewId,e.SubmissionReviewId,
CASE WHEN ( e.SubmissionReviewId IS NULL
OR p.SubmissionReviewId IS NULL
) THEN 'Fail'
ELSE 'Pass'
END
FROM #Present p
LEFT JOIN #Expected e ON e.SubmissionReviewId = p.SubmissionReviewId
UNION
SELECT p.SubmissionReviewId,e.SubmissionReviewId ,
CASE WHEN ( e.SubmissionReviewId IS NULL
OR p.SubmissionReviewId IS NULL
) THEN 'Fail'
ELSE 'Pass'
END
FROM #Present p
RIGHT JOIN #Expected e ON e.SubmissionReviewId = p.SubmissionReviewId;
3. Outside of the cursor I set up a new parameter that takes any fails if they exist or 'pass' if they don't
SET #Result = ( SELECT DISTINCT TOP 1
TestStatus
FROM #ActualAssert
ORDER BY TestStatus ASC
);
4. Then I modified the assert to fail if #result is anything other than 'Pass'
EXEC tSQLt.AssertEqualsString #Expected = N'Pass', -- nvarchar(max)
#Actual = #Result, #Message = N''; -- nvarchar(max)
** A note I change previous present and expected temp tables into variable tables
We have our main database on a server, there is this stored procedure; when we run it against the database, it returns wrong values.
But when I take a back up of this database and restore it on another server and run the exact same query, it returns the correct answer.
What can I do?
Is it possible that the configuration of SQL Server affects how a query returns results?
If yes where can I start looking for problem ?
Here is the stored procedure, the exact same procedure runs on both databases and both databases are identical.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[S_GheymatGozaryFIFOFroosh]
#AYear SMALLINT,
#LDate CHAR(8),
#OdCd VARCHAR(17),
#FromFirst BIT,
#SCd TINYINT
AS
DECLARE #LHId Int, #LHRadif SmallInt,
#LHFact_Date CHAR(8), #LHFact_No INT,
#LHStock_Cd TinyInt, #LQnt_Resid DECIMAL(18,4),
#LPrc_Resid DECIMAL(30,8)
DECLARE #LRId INT, #LRRadif SmallInt,
#LRFact_Date CHAR(8), #LRFact_No INT,
#LRStock_Cd TinyInt
DECLARE #Kind_Cd TINYINT, #StartDate CHAR(8)
DECLARE #Cnt INT
SET #Cnt = 0
IF #ldate IS NOT NULL AND #FromFirst = 1
BEGIN
DELETE FROM S_Fifo_Gheymat
WHERE (Acc_Year = #Ayear)
AND (#SCd = 0 OR H_Stock_Cd = #SCd)
AND (Od_Cd = #OdCd)
END
IF #SCd = 0
SET #Kind_Cd = 2
ELSE
SET #Kind_Cd = 1
SET #StartDate = Right(CAST(#AYear AS VARCHAR(4)), 2) + '/01/01'
SELECT
#LHId = H_Id,
#LHRadif = H_Radif,
#LHFact_Date = H_Fact_Date,
#LHFact_No = H_Fact_No,
#LHStock_Cd = H_Stock_Cd,
#LQnt_Resid = Qnt_Resid,
#LPrc_Resid = Prc_Resid,
#LRId = R_Id,
#LRRadif = R_Radif,
#LRFact_Date = R_Fact_Date,
#LRFact_No = R_Fact_No,
#LRStock_Cd = R_Stock_Cd
FROM
S_Fifo_Gheymat
WHERE
Acc_Year = #AYear
AND Od_Cd = #OdCd
AND (#SCd = 0 OR H_Stock_Cd = #SCd)
AND EXISTS (SELECT Id
FROM S_Dtl_Fct
WHERE Id = H_Id
AND Radif = H_Radif
AND Stock_Cd = H_Stock_Cd
AND Od_Cd = S_Fifo_Gheymat.Od_Cd)
AND EXISTS (SELECT Id
FROM S_Dtl_Fct
WHERE Id = R_Id
AND Radif = R_Radif
AND Stock_Cd = R_Stock_Cd
AND Od_Cd = S_Fifo_Gheymat.Od_Cd)
SELECT #LHId=ISNULL(#LHId,0),#LHRadif=IsNull(#LHRadif,0),#LHFact_Date=IsNull
(#LHFact_Date,#StartDate),#LHFact_No=IsNull(#LHFact_No,0),#LHStock_Cd=ISNULL
(#LHStock_Cd,0)
,#LQnt_Resid=ISNULL(#LQnt_Resid,0),#LPrc_Resid=ISNULL(#LPrc_Resid,0)
,#LRId=ISNULL(#LRId,0),#LRRadif=IsNull(#LRRadif,0),#LRFact_Date=IsNull
(#LRFact_Date,#StartDate),#LRFact_No=IsNull(#LRFact_No,0),#LRStock_Cd=ISNULL
(#LRStock_Cd,0)
---------------------------------------
IF #LDate IS NULL BEGIN
SELECT TOP 1 #LDate=Fact_Date
FROM S_Dtl_Fct D
LEFT OUTER JOIN S_Hed_Fct H ON D.Id=H.Id
LEFT OUTER JOIN dbo.S_STOCKS S ON D.Stock_Cd=S.Stock_Cd
LEFT OUTER JOIN U_Log U ON H.Id_Log=U.Id_Log AND U.Action_Cd=5
WHERE (H.Acc_Year=#AYear) AND (H.Flag=6) AND (D.Od_Cd=#OdCd) AND
(H.Tamam=0) AND (#SCd<>0 OR S.Estesna_Gp=0)
AND (
(H.Fact_Date>#LHFact_Date)
OR (H.Fact_Date=#LHFact_Date AND
H.Fact_No>#LHFact_No)
OR (H.Fact_Date=#LHFact_Date AND
H.Fact_No=#LHFact_No AND D.Radif>#LHRadif)
OR (H.Fact_Date=#LHFact_Date AND
H.Fact_No=#LHFact_No AND D.Radif=#LHRadif AND D.Stock_Cd>#LHStock_Cd)
)
AND (#SCd=0 OR D.Stock_Cd=#SCd) AND (H.VAZEIAT<>2) AND
(U.Id_Log IS NOT NULL)
ORDER BY H.Fact_Date
End
DECLARE #H TABLE ( H_Id INT,H_Radif SMALLINT,H_Fact_Date CHAR
(8),H_Fact_No INT,H_Stock_Cd TINYINT,Quantity Decimal(18,4),Un_Prc
MONEY,HTamam Bit
,R_Id INT,R_Radif SMALLINT,R_Fact_Date
CHAR(8),R_Fact_No INT,R_Stock_Cd TINYINT,Qnt_Resid Decimal(18,2),Prc_Resid
Decimal(30,8))
INSERT INTO #H
(H_Id,H_Radif,H_Fact_Date,H_Fact_No,H_Stock_Cd,Quantity,HTamam)
SELECT D.Id,D.Radif,H.Fact_Date,H.Fact_No,D.Stock_Cd,D.Quantity,H.Tamam
FROM S_Dtl_Fct D
LEFT OUTER JOIN S_Hed_Fct H ON D.Id=H.Id
LEFT OUTER JOIN dbo.S_STOCKS S ON D.Stock_Cd=S.Stock_Cd
WHERE (H.Acc_Year=#AYear) AND (H.Flag=6) AND (D.Od_Cd=#OdCd) AND
(H.Fact_Date<=#LDate) AND (#SCd<>0 OR S.Estesna_Gp=0)
AND (
(H.Fact_Date>#LHFact_Date)
OR (H.Fact_Date=#LHFact_Date AND H.Fact_No>#LHFact_No)
OR (H.Fact_Date=#LHFact_Date AND H.Fact_No=#LHFact_No
AND D.Radif>#LHRadif)
OR (H.Fact_Date=#LHFact_Date AND H.Fact_No=#LHFact_No
AND D.Radif=#LHRadif AND D.Stock_Cd>#LHStock_Cd)
)
AND (#SCd=0 OR D.Stock_Cd=#SCd) AND (H.VAZEIAT<>2)
ORDER BY H.Fact_Date,H.Fact_No,D.Radif,D.Stock_Cd
Delete S_Related_RH FROM #H H LEFT OUTER JOIN S_Related_RH R ON
H.H_Id=R.H_Id AND H.H_Radif=R.H_Radif
------------------------------------------
DECLARE #HQnt DECIMAL(18,4),#HDate CHAR(8),#SumQ DECIMAL(18,4),#SumG
MONEY,#HQntWithPrc DECIMAL(18,4)
SET #SumG=#LQnt_Resid*#LPrc_Resid
SET #SumQ=#LQnt_Resid
--
DECLARE Cr CURSOR FOR SELECT Quantity,H_Fact_Date,H_Id,H_Radif FROM #H FOR
UPDATE OF Un_Prc
Open Cr
Fetch Next From Cr InTo #HQnt,#HDate,#LHId,#LHRadif
While (##Fetch_Status=0) AND (#LRId IS NOT NULL)
Begin
IF #HQnt<=#LQnt_Resid BEGIN
SET #LQnt_Resid=#LQnt_Resid-#HQnt
UPDATE #H SET
Un_Prc=#SumG/#SumQ,R_Id=#LRId,R_Radif=#LRRadif,R_Fact_Date=#LRFact_Date,
R_Fact_No=#LRFact_No,R_Stock_Cd=#LRStock_Cd
,Qnt_Resid=#LQnt_Resid,Prc_Resid=#LPrc_Resid
WHERE CURRENT OF Cr
IF #HQnt>0 BEGIN
INSERT INTO dbo.S_Related_RH
(H_Id,H_Radif,R_Id,R_Radif,Quantity)
VALUES (#LHId,#LHRadif,#LRId,#LRRadif,#HQnt)
END
SET #SumG=#LQnt_Resid*#LPrc_Resid
SET #SumQ=#LQnt_Resid
Fetch Next From Cr InTo #HQnt,#HDate,#LHId,#LHRadif
END ELSE BEGIN
IF #LQnt_Resid>0 BEGIN
INSERT INTO dbo.S_Related_RH
(H_Id,H_Radif,R_Id,R_Radif,Quantity)
VALUES (#LHId,#LHRadif,#LRId,#LRRadif,#LQnt_Resid)
END
SET #HQnt=#HQnt-#LQnt_Resid --مقدار باقیمانده حواله
SELECT TOP 1
#LRId=D.Id,#LRRadif=D.Radif,#LRFact_Date=H.Fact_Date,#LRFact_No=H.Fact_No,
#LRStock_Cd=D.Stock_Cd,#LQnt_Resid=D.QUANTITY
,#LPrc_Resid=CASE D.QUANTITY WHEN 0
THEN 0 ELSE ( (Un_Prc*D.QUANTITY)+ISNULL(Qnt_1,0) )/ D.QUANTITY END
FROM S_Dtl_Fct D
LEFT OUTER JOIN S_Hed_Fct H ON D.Id=H.Id
LEFT OUTER JOIN dbo.S_STOCKS S ON D.Stock_Cd=S.Stock_Cd
WHERE (H.Acc_Year=#AYear) AND (H.Flag=5) AND (D.Od_Cd=#OdCd)
AND (H.Fact_Date<=#HDate) AND (H.Tamam=1) AND (#SCd<>0 OR S.Estesna_Gp=0)
AND (
(H.Fact_Date>#LRFact_Date)
OR (H.Fact_Date=#LRFact_Date AND
H.Fact_No>#LRFact_No)
OR (H.Fact_Date=#LRFact_Date AND
H.Fact_No=#LRFact_No AND D.Radif>#LRRadif)
OR (H.Fact_Date=#LRFact_Date AND
H.Fact_No=#LRFact_No AND D.Radif=#LRRadif AND D.Stock_Cd>#LRStock_Cd)
)
AND (#SCd=0 OR D.Stock_Cd=#SCd) AND (H.VAZEIAT<>2)
ORDER BY H.Fact_Date,H.Fact_No,D.Radif,D.Stock_Cd
--
IF #LRId IS NOT NULL BEGIN
IF #HQnt<=#LQnt_Resid SET #HQntWithPrc=#HQnt ELSE SET
#HQntWithPrc=#LQnt_Resid
SET #SumG=#SumG+(#HQntWithPrc*#LPrc_Resid)
SET #SumQ=#SumQ+#HQntWithPrc
End
IF ISNULL(#LQnt_Resid,0)=0 Break
End
END
Close Cr
Deallocate Cr
DECLARE #E Int
SET #E=0
BEGIN TRAN
UPDATE D SET Un_Prc=G.Un_Prc
FROM S_Dtl_Fct D
INNER JOIN #H G ON D.Id=G.H_Id AND D.Radif=G.H_Radif
WHERE (G.HTamam=0) And (G.R_Id IS NOT NULL)
SET #Cnt=##ROWCOUNT
Set #E=#E+##Error
DELETE F FROM S_Fifo_Gheymat F
WHERE (Acc_Year=#Ayear) AND (#SCd=0 OR H_Stock_Cd=#SCd) AND
(Od_Cd=#OdCd)
And EXISTS (SELECT TOP 1 Od_Cd
FROM #H
WHERE (H_Stock_Cd=F.H_Stock_Cd) AND
(Od_Cd=#OdCd) AND (R_Id IS NOT NULL)
ORDER BY H_Fact_Date DESC ,H_Fact_No
DESC ,H_Radif DESC ,H_Stock_Cd DESC)
Set #E=#E+##Error
INSERT INTO S_Fifo_Gheymat
(Acc_Year,H_Stock_Cd,OD_CD,R_Stock_Cd,H_Id,H_Fact_Date,H_Fact_No,
H_Radif,R_Id,R_Fact_Date,R_Fact_No,R_Radif,Qnt_Resid,Prc_Resid)
SELECT TOP 1
#AYear,H_Stock_Cd,#OdCd,R_Stock_Cd,H_Id,H_Fact_Date,H_Fact_No,H_Radif,
R_Id,R_Fact_Date,R_Fact_No,R_Radif,Qnt_Resid,Prc_Resid
FROM #H
WHERE R_Id IS NOT Null
ORDER BY H_Fact_Date DESC ,H_Fact_No DESC ,H_Radif DESC ,H_Stock_Cd Desc
Set #E=#E+##Error
IF #E=0 COMMIT TRAN ELSE ROLLBACK TRAN
SELECT #Cnt Cnt,#LHFact_No LHFactNo,#LHFact_Date LHFactDate,#LHStock_Cd
LHStock_Cd,#LRFact_No LRFactNo,#LRFact_Date LRFactDate,#LRStock_Cd
LRStock_Cd
Without a copy of your db (not a request) it's not possible to answer this.
Is it possible that the configuration of SQL Server affects how a
query returns results?
Yes this is a possibility. For example, if your ANSI NULL settings are different between the two servers then NULL will be equal to NULL on the server has ANSI_NULL set to on OFF but not on the server where ANSI_NULL is ON. Collation is another. If one server has a case sensitive collation the "A" and "a" are not equal whereas the opposite is true using the SQL Server default. These are just a couple examples.
That said, they way to isolate the problem is to break the stored proc up into parts and try to identify where the differences are starting. In the first steps, where you assign variables, add a step to dump them into a temp table that you can summarize and compare across both servers. If there's no differences keep moving down the proc running each part until you find a difference. Often I'll comment everything out then uncomment code from top-to-bottom until I isolate the problem.
Lastly, you are using couple cursors here and don't need to. You can simplify your code by making it more set-based and therefore less verbose. It will be much easier to troubleshoot and will perform much, much better.
The reason of creating a stored procedure is to schedule a job to send a biweekly report to our staff (coordinators) using SQL Server db mail.
I'm having problems with getting it to work the right way. I don't usually work with cursors but couldn't find other choices.
Here's the issue. I tested the query by set criteria to send only to one Coordinator with one record "if #Coord_Email = 'lamez.sw1#gmail.com', where n.id = '43422546'". However the query been running over 5 minutes so i had to cancel it.
ALTER PROCEDURE [dbo].[sp_MZ_Coord_rpt_s9]
AS
BEGIN
DECLARE #Member_ID VARCHAR(20)
DECLARE Report_S9 CURSOR FOR
SELECT id
FROM name
WHERE status = 'a'
OPEN Report_S9
FETCH NEXT FROM Report_S9 INTO #member_ID
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #Coord_ID Varchar(20)
DECLARE #CO_ID Varchar(20)
DECLARE #Coord_Name Varchar(50)
DECLARE #Coord_Email Varchar(50)
SELECT #CO_ID = ID
FROM Relationship
WHERE id = #Member_ID
SELECT #Coord_ID = target_id
FROM Relationship
WHERE RELATION_TYPE = 'CO'
SELECT #Coord_Name = FULL_NAME
FROM Name
WHERE ID = #Coord_ID
SELECT #Coord_Email = email
FROM Name
WHERE id = #Coord_ID
IF #Coord_Email <> ''
BEGIN
SELECT
n.id, n.CO_ID, n.FULL_NAME, a.TRANSACTION_DATE, a.UF_1, r.TARGET_ID
FROM name n
INNER JOIN activity a ON n.id = a.id
INNER JOIN Tops_Profile tp ON a.id = tp.ID
INNER JOIN Relationship r ON n.CO_ID = r.ID
WHERE
n.id = #member
AND UF_1 <> ''
AND (DATEDIFF(dd, TRANSACTION_DATE, GETDATE()) < 2)
AND r.RELATION_TYPE = 'co'
ORDER BY
TRANSACTION_DATE
EXEC msdb..sp_send_dbmail
#profile_name = 'TOPS.ADMIN',
#recipients = #Coord_Email,
--#blind_copy_recipients = ,
#subject = 'S9 Report'
End
FETCH NEXT FROM Report_S9 INTO #member_ID
END
CLOSE Report_S9
DEALLOCAT Report_S9
End
Any help is greatly appreciated.
The FETCH NEXT should be outside of your check for null. You need to continue the loop, even when there is nothing to do.
I have a problem with name of database in a cursor.
Here the current code
DECLARE #IDES INT
DECLARE #IDPROD INT
DECLARE #count INT
SET #count = 0
DECLARE CUR_CONSO CURSOR LOCAL fast_forward FOR
SELECT E2.id_es ,P3.id_prod FROM
[gpto_v004p001].[dbo].[GPTO_PRODETAB] P1
INNER JOIN
[fer_v008].[dbo].[T_PRODUIT] P3
ON P3.GPTO_PRODUIT_ID = P1.GPTO_PRODUIT_ID
INNER JOIN [gpto_v004p001].[dbo].[GPTO_ETAB] E1
ON E1.ETABID = P1.ETABID
INNER JOIN
[fer_v008].[dbo].[t_etablissement] E2
ON E1.ETABUC = LEFT(E2.code_es,5)
LEFT JOIN
[fer_v008].[dbo].[t_produit_etablissement] PE1
ON PE1.id_prod = P3.id_prod AND PE1.id_es = E2.id_es
WHERE PE1.id_es IS NULL AND GPTO_PRODUIT_ETAPE = 4
OPEN CUR_CONSO
FETCH CUR_CONSO INTO #IDES , #IDPROD
WHILE ##FETCH_STATUS = 0
BEGIN
IF NOT EXISTS (Select * from [fer_v008].[dbo].[t_produit_etablissement] where id_es=#IDES and id_prod=#IDPROD) -- Pas d'enregistrements
BEGIN
INSERT INTO [fer_v008].[dbo].[t_produit_etablissement]
([id_es],[id_prod],[gest_prod])
VALUES
(#IDES,#IDPROD,0)
SET #count = #count + 1
END
FETCH CUR_CONSO INTO #IDES , #IDPROD
END
CLOSE CUR_CONSO
DEALLOCATE CUR_CONSO
As the database is versionned, I need to use database name as variable saved in parameter table.
For easy script, I use Execute command as this
DECLARE #base_travail varchar(128)
SELECT #base_travail = val_str_par FROM t_parametre WHERE nom_par = 'base_travail'
DECLARE #execcmd varchar(max)
SET #execcmd = 'insert into #tmpfiltres SELECT TOP 1 filtre_exu FROM '
+ #base_travail + '.dbo.t_export_util WHERE id_exu =' + convert(varchar,#id_exu)
Execute (#execcmd)
But how do this when I have a cursor ? The 1st sample code is just a sample, whole script go over 400 lines, so I can't switch all the script in string mode.
Thanks for your help.
I had the same issue. Had to do with Database Compatibility Level.
This Code:
DECLARE #VARSql varchar(2000), #ID int;
SET #VARSql = 'USE [SomeOtherDatabase]; DECLARE cur CURSOR GLOBAL for
SELECT Max(SomeTableID) FROM [dbo].[SomeTable];';
Exec(#VARSql); open cur; fetch next from cur into #ID; close cur; deallocate cur;
PRINT #ID
Generated this error:
Msg 16958, Level 16, State 3, Line 3
Could not complete cursor operation because the set options have changed since the cursor was declared.
Running on SQL 2008 server.
Calling database has Compatibility Level 90 (Sql Svr 2005).
SomeOtherDatabase in code above has Compatibility Level 100 (Sql Svr 2008).
If you alter compatibility level so calling and called databases are the same, problem resolved.
select * from sys.databases
ALTER DATABASE [CallingDatabase] SET COMPATIBILITY_LEVEL = 100;
I had a same problem. Here is my solution;
DECLARE CUR_CORSO CURSOR **FAST_FORWARD FORWARD_ONLY** FOR
...