Subquery in DECLARE statement brings back more than one value - sql-server

I have the stored procedure below that I need help on. Its purpose is to find differences between a staging DB and the production DB. When it finds the difference, the stored procedure will update the production DB with the correct information. The problem is that sometimes there is more than one difference between the DBs. The stored procedure can only handle one difference between the DBs at a time. I want the stored procedure to be able to handle as many differences as it finds. If it can only handle one difference at a time, the stored procedure would need to be running continually. Any ideas or help is greatly appreciated.
`BEGIN TRANSACTION
DECLARE #FILENUM NVARCHAR(30)
SET #FILENUM = ( SELECT TOP 1 B.ID FROM DBO.ABC_FILE_NUMBER F WITH ( NOLOCK )
JOIN DBO.REL_PRIMARY_NUMBER R WITH ( NOLOCK ) ON F.ID = R.FILE_NUMBER_ID
JOIN DBO.ABC_PRIMARY_NUMBER P WITH ( NOLOCK ) ON R.PRIMARY_NUMBER_ID = P.ID
JOIN DBO.STAGINGDATA S WITH ( NOLOCK ) ON F.FILE_NUMBER_ALIAS = S.ID
WHERE S.PRIMARYNUMBER <> P.PRIMARY_NUMBER_ALIAS)
DECLARE #PRIMNUM NVARCHAR(30)
SET #PRIMNUM = ( SELECT DISTINCT P.ID FROM DBO.STAGINGDATA S WITH ( NOLOCK )
JOIN DBO.ABC_PRIMARY_NUMBER P WITH ( NOLOCK ) ON P.PRIMARY_NUMBER_ALIAS = S.PRIMARYNUMBER
WHERE S.ID = ( SELECT F.FILE_NUMBER_ALIAS FROM ABC_FILE_NUMBER WHERE ID = #FILENUM))
UPDATE DBO.REL_PRIMARY_NUMBER
SET PRIMARY_NUMBER_ID = #PRIMNUM
WHERE FILE_NUMBER_ID = #FILENUM
UPDATE DBO.ABC_WORKSPACE
SET PRIMARY_NUMBER_ID = #PRIMNUM
WHERE FILE_NUMBER_ID = #FILENUM
UPDATE DBO.ABC_DOCUMENT
SET PRIMARY_NUMBER_ID = #PRIMNUM
WHERE FILE_NUMBER_ID = #FILENUM
UPDATE DBO.ABC_FILE_NUMBER
SET MODIFIED_TIME = GETDATE(), MODIFIED_BY_ID = '21403'
WHERE FILE_NUMBER_ID = #FILENUM
COMMIT`

You can construct a loop as below to "walk" through each #FILENUM and do the work using the same scripts you are using now. A better option would be to rewrite each DML operation to perform the work in a set based way and act on all the rows at once, but that might not be an option for you depending on what other actions you are performing.
Here's a simple setup to loop through each FileNum:
declare #Process table (ProcessId int identity(1,1), FileNum nvarchar(30));
-- stage *all* the fileNums (perhaps in some order?)
insert into #Process (FileNum)
SELECT B.ID FROM DBO.ABC_FILE_NUMBER F WITH ( NOLOCK )
JOIN DBO.REL_PRIMARY_NUMBER R WITH ( NOLOCK ) ON F.ID = R.FILE_NUMBER_I
JOIN DBO.ABC_PRIMARY_NUMBER P WITH ( NOLOCK ) ON R.PRIMARY_NUMBER_ID = P.ID
JOIN DBO.STAGINGDATA S WITH ( NOLOCK ) ON F.FILE_NUMBER_ALIAS = S.ID
WHERE S.PRIMARYNUMBER <> P.PRIMARY_NUMBER_ALIAS
declare #ProcessId int,
#FileNum nvarchar(30);
select #ProcessId = min(ProcessId) from #Process;
while #ProcessId is not null
begin
select #FileNum = FileNum from #Process where ProcessId = #ProcessId;
print 'Working on FileNum: ' + #FileNum;
/*
do your work here
*/
select #ProcessId = min(ProcessId) from #Process where ProcessId > #ProcessId;
end
The set based operation would look something like:
declare #Stage table (FileNum nvarchar(30), PrimNum nvarchar(30) primary key (FileNum));
-- stage the (FileNum:PrimNum) dataset
insert into #Stage (FileNum)
select FileNum, PrimNum from dbo.yourTables where yourColumn ...
--now perform set based updates
UPDATE rpn
SET PRIMARY_NUMBER_ID = s.PRIMNUM
from #Stage s
join DBO.REL_PRIMARY_NUMBER rpn on
s.FileNum = rpn.FILE_NUMBER_ID
UPDATE aw
SET PRIMARY_NUMBER_ID = s.PRIMNUM
from #Stage s
join DBO.ABC_WORKSPACE aw on
s.FileNum = aw.FILE_NUMBER_ID
-- and so on...

Related

SQL Server - update multiple records using a stored procedure

Being a super novice at this, I would like some guidance on this, please.
I need to compare two sets of data and update one set with a value. This is what I have so far.
PROCEDURE [dbo].[update_personnel_rank]
AS
DECLARE #frsid VARCHAR
DECLARE #officerid VARCHAR
DECLARE #hrrank VARCHAR
DECLARE #personnelrank VARCHAR
DECLARE #farank VARCHAR
DECLARE #rank VARCHAR(150)
SET #rank = 'Admin Spec II'
BEGIN
SET NOCOUNT ON;
SELECT
#frsid = hr.FRSID,
#officerid = p.OfficerID,
#hrrank = hr.Rank,
#personnelrank = p.Rank,
#farank = r.FA_Rank
FROM
[FireApp_REPL_DW_Data].[dbo].[MCFRSCombinedPersonnelandPimsStaff] hr
INNER JOIN
[fh_reports].[dbo].[personnel_bk] p ON p.OfficerID = hr.FRSID
INNER JOIN
[fh_reports].[dbo].[Rank_Lookup_tbl] r ON r.FA_Rank = hr.Rank
WHERE
(p.rank <> hr.Rank OR p.rank = '')
AND p.Rank = #rank
UPDATE [fh_reports].[dbo].[personnel_bk]
SET Rank = #farank
WHERE OfficerID = #officerid
END
GO
The select query returns 3 records and this stored procedure runs without any error, but it does not update the records. Since the select query returns 3 records, I think I need to change the parameter setting accordingly, but not sure how...
To #Sami's point, if you are not returning those variables, you do not need to set them and can instead just run the update:
USE [YourDatabase]
GO
SET NOCOUNT ON
GO
ALTER PROCEDURE [dbo].[update_personnel_rank]
#rank VARCHAR(150) --= 'Admin Spec II'
AS
BEGIN
IF #rank IS NULL OR #rank = ''
RAISERROR('Please enter a valid rank string.', 16, 1)
UPDATE hr
SET [Rank] = r.FA_Rank
FROM [FireApp_REPL_DW_Data].[dbo].[MCFRSCombinedPersonnelandPimsStaff] [hr]
INNER JOIN [fh_reports].[dbo].[personnel_bk] [p]
ON [p].[OfficerID] = [hr].[FRSID]
INNER JOIN [fh_reports].[dbo].[Rank_Lookup_tbl] [r]
ON [r].[FA_Rank] = [hr].[Rank]
WHERE [p].[rank] <> [hr].[Rank]
AND ([p].[Rank] = #rank OR p.[Rank] = '')
END ;
GO

Same query, same database, different server, different result

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.

Translate code from SQL SERVER using temporary table to Oracle PLSQL using Cursor

How could I transform a temporary table to make an update in SQL server to an equivalent code in PLSQL with a cursor?
ALTER proc [dbo].[sp_lista] (#pcFI datetime, #pcFF datetime, #vSuma tinyint) as
begin tran
Declare #crLista Table (
NEnt int,
NEje int,
NExp char(17),
NAcu char(17),
NSen char(17)
)
if #vSuma = 0
begin
insert into #crLista
select tablax.num_entrada, tablax.ejercicio, tablax.num_expediente, tablax.num_acuerdo, tablax.num_sentencia, tablax.descripcion
from tablax inner join tablaz on
tablaz.num_expediente = tablax.num_expediente
where tablax.est_suma = 0 and (EXISTS
( SELECT 1
FROM tablay
WHERE tablay.cve_usuario = SESSION_USER
and tablay.cve_region = tablaz.cve_region
and tablay.cve_sala = tablaz.cve_sala
and tablay.cve_mag = tablaz.cve_mag
and tablay.cve_srio = tablaz.cve_srio) )
update tablax
set notificado = 1,
fec_notificado = getdate()
from #crLista MLista
where MLista.NEnt = tablax.num_entrada and
MLista.NEje = tablax.ejercicio and tablax.est_suma = #vSuma
In PL/SQL I have something like the following:
create or replace PROCEDURE sp_lista(
v_pcFI IN DATE,
v_pcFF IN DATE,
v_vSuma IN NUMBER
)
AS
vcMLista SYS_REFCURSOR;
BEGIN
IF v_vSuma = 0 THEN
BEGIN
open vcMLista for
SELECT tablax.num_entrada ,
tablax.ejercicio ,
tablax.num_expediente ,
tablax.num_acuerdo ,
tablax.num_sentencia
FROM tablax
JOIN tablaz
ON tablaz.num_expediente = tablax.num_expediente
WHERE tablax.est_suma = 0
AND ( EXISTS
( SELECT 1
FROM tablay
WHERE tablay.cve_usuario = v_vcUsr_actual
AND tablay.cve_region = tablaz.cve_region
AND tablay.cve_sala = tablaz.cve_sala
AND tablay.cve_mag = tablaz.cve_mag
AND tablay.cve_srio = tablaz.cve_srio
) )
FOR UPDATE;
Subsequently in SQL SERVER a temporary table is used and the following is done:
update tablax
set notificado = 1,
fec_notificado = getdate()
from #crLista MLista
where MLista.NEnt = tablax.num_entrada and
MLista.NEje = tablax.ejercicio and tablax.est_suma = #vSuma
update tablay set fmod =getdate()
where ndoc in
( select distinct NExp from #crLista )
How can I do the PLSQL equivalent with a cursor? I've tried the following:
OPEN crLista;
FETCH crLista INTO reg;
WHILE crLista%FOUND LOOP
UPDATE actm_lista SET
notificado = 1,
FEC_NOTIFICADO = sysdate
WHERE CURRENT OF crLista;
FETCH crLista INTO reg;
END LOOP;
OPEN crLista;
FETCH crLista INTO reg;
WHILE crLista%FOUND LOOP
UPDATE tablax
SET fmod = SYSDATE
WHERE ne IN
( SELECT DISTINCT reg.ne FROM crLista );
FETCH crLista INTO reg;
END LOOP;
UPDATE tablay
SET fmod = SYSDATE
WHERE ndoc IN
( SELECT DISTINCT ndoc FROM crLista );
But when trying to do the "from crLista" I get the error "the table or view does not exist".
You can't query a cursor as if it was a table. They are completely different things. All you can do with a cursor is open, fetch, and close.
Since you need to use the results in two places, it might be worth creating a global temporary table. You'll have to define this separately, as the definition is permanent like a normal table - it's just the contents that are private to your session.
You might also look at bulk-fetching the results into a collection and using two forall statements, as in this question:
bulk collect using "for update"
(In that example the only issue was around adding a for update clause, which you can ignore.)

Already an object named in the database issue

I am trying to execute an email that contains the results of a stored procedure. I was looking at other posts in stackoverflow but cannot seem to get past an error that states "Msg 2714, Level 16, State 1, Procedure CompareConfirm_FraudRules, Line 38
There is already an object named '##returnInactiveRules' in the database." I've looked in the DB and there is no object that exists with this name already. Any suggestions on how to fix this issue would be appreciated. Thanks.
Here is the my SP:
BEGIN
CREATE TABLE ##returnInactiveRules (
ProductName varchar(100),
ChannelName varchar(100),
StrategyCode varchar(100),
StrategyName varchar(100),
RuleCode varchar(100),
RuleName varchar(100),
On_Off varchar(5)
);
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
-- SELECT R.RuleCode, R.Name as RuleName, S.StrategyCode, S.Name as StrategyName, R.IsActive
SELECT DISTINCT
CASE
WHEN PC.ProductIdentifier='2000' THEN 'GP'
WHEN PC.ProductIdentifier='1000' THEN 'MB'
END as ProductName, C.Name as ChannelName, S.StrategyCode, S.Name as StrategyName, R.RuleCode, R.Name as RuleName,
CASE
WHEN R.IsActive = 1 THEN 'On'
WHEN R.IsActive = 0 THEN 'Off'
END as On_Off
INTO ##returnInactiveRules
FROM dbo.[Rule] R
INNER JOIN dbo.Strategy S
on S.KnockoutRuleSet = R.KnockoutRuleSet
INNER JOIN dbo.RFAI P
on R.RFAIId = P.RFAIId
INNER JOIN dbo.DecisionStatus D
on D. StatusId = R. StatusId
LEFT OUTER JOIN dbo.NOAA N
on N.NOAAId = R.NOAAId
INNER JOIN dbo.RuleQuestionsXRef Q
ON Q.RuleId = R.RuleId
INNER JOIN ProductChannelStrategyRuleXref X
ON X.RuleId = R.RuleId
INNER JOIN ProductChannelStrategy CS
ON CS.ProductChannelStrategyId = X.ProductChannelStrategyId
INNER JOIN ProductChannel PC
ON PC.ProductChannelId = CS.ProductChannelId
INNER JOIN dbo.Channel C
ON C.ChannelId = PC.ChannelId
WHERE R.IsActive = 0
AND R.RuleCode IN ('F06',
'F07',
'F11',
'F12',
'F14',
'F15',
'F16',
'F17',
'F19',
'F23',
'F25',
'F26',
'F10'
)
-- ORDER BY R.RuleCode, R.Name;
ORDER BY ProductName, C.Name, S.StrategyCode, S.Name, R.RuleCode, R.Name;
-- SELECT * FROM #returnValue;
-- Email the results in the #returnValue table --
EXEC msdb.dbo.sp_send_dbmail
#execute_query_database='Prod-XXX',
#recipients=N'msavoy#xxx.com',
#body='Attached please find a file with the results.',
#subject ='Compare Fraud Rule Results',
#profile_name ='Reports',
#query ='EXEC CompareConfirm_Rules',
#attach_query_result_as_file = 1,
#query_attachment_filename ='CompareRuleResults.txt'
END
DROP TABLE ##returnInactiveRules;
GO
If exists Drop it, then create the table
IF Object_id('tempdb..##returnInactiveRules') IS NOT NULL
DROP TABLE ##returnInactiveRules
CREATE TABLE ##returnInactiveRules
(
ProductName VARCHAR(100),
ChannelName VARCHAR(100),
StrategyCode VARCHAR(100),
StrategyName VARCHAR(100),
RuleCode VARCHAR(100),
RuleName VARCHAR(100),
On_Off VARCHAR(5)
);
Temp tables which start with ## are global temp tables, so if you have 2 connection opened, and one of them created a table called ##Temp, you would not be able to create the same table from connection 2, until it is dropped by any of the 2 connections.
Best thing would be to use #returnInactiveRules and check for existence before creating it.
IF OBJECT_ID('tempdb..#returnInactiveRules') IS NOT NULL
DROP TABLE #returnInactiveRules
GO
Have the drop statement at the beginning and if it's a global temp table ensure that only one process is creating it at any one time as two cannot exist simultaneously..
Also, unless you require other sessions to access the data, consider using a temp table rather than a global temp table by replacing the ## with #

Update Large Number of rows in sql server

I'm trying to update a column in a table which has ~90,000 rows. Is there is any optimized way to update the table?
I have added necessary indexes.. so that no table scans/lookups are not happening. But still it takes much time to run (1hr).
My scenario:
DECLARE #ParentID NVARCHAR(100),
#Con_ERID INT
DECLARE #MaxCount INT,
#MinCount INT,
#Id INT
SELECT #MaxCount = MAX(Id) from [dbo].[ParentIDStaging] where Type='grid'
SET #MinCount = 1
WHILE #MinCount <= #MaxCount
BEGIN
SELECT #Id = ConID FROM [dbo].[ParentIDStaging] WHERE Id = #MinCount and Type = 'grid'
IF #Id IS NOT NULL
BEGIN
SELECT #Con_ERID = ErId FROM Context (NOLOCK) Where ConId = #Id
SELECT #ParentID = Identifier FROM Recording (NOLOCK) where ErId = #Con_ERID
BEGIN TRAN
UPDATE [ParentIDStaging] WITH (ROWLOCK)
SET [ParentID] = #ParentID
WHERE ContentType = 'grid'
AND ConID = #Id
COMMIT
END
SET #MinCount = #MinCount + 1
END
Looping is slow. Try doing it in one update with include the relevant other tables using joins. Your query can probably be writen like this (don't know your actual schema):
UPDATE PS
SET PS.ParentID = Recording.Identifier
FROM ParetnIDStaging PS
JOIN Context on (Context.ConId = PS.ConId)
JOIN Recording on (Recording.ErId = Context.ErId)
WHERE ...
It is because you are looping and updating one record at a time and using explicit locks/transactions.
Without knowing your underlying structure - I would bet you could do what you are trying with an update from a select.
UPDATE ParentIDStaging
SET parentIdStaging.ParentID=recording.Identifier
from ParentIDStaging
join Context on context.ConId = ParentIDStaging.ConId
join recording on contect.erid=recording.erId
WHERE parentIdStaging.ContentType = 'grid'
AND parentidStaging.Type='grid'

Resources