Stored procedure only executes correctly on first execution - sql-server

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

Related

Issues with creating label for our M1 erp software

I am trying to convert an SQL that was written for a previous version of our software. It is grabbing information from an input form, placing them in a temporary table and calculating number of labels and printing a crystal report label accordingly
I have tried changing syntax and removing a where clause ( it is commented out in my code below) that i was unable to link to anything in our new version.
SET NOCOUNT ON
DECLARE #nloop int, #nLabels int
DECLARE #rmlReceiptID varchar(10), #rmlReceiptLineID int, #urmlNOofLabels int
DECLARE LabelsCursor CURSOR READ_ONLY FOR SELECT #rmlReceiptID, #rmlReceiptLineID, #urmlNOofLabels FROM ReceiptLines /* WHERE {?WHERECLAUSE}*/ ORDER BY rmlReceiptID, rmlReceiptLineID
CREATE TABLE #UReceiptLabel (rmlReceiptID varchar(10), rmlReceiptLineID int, CurrentLabel int, TotalLabels int)
SELECT #rmlReceiptID,#rmlReceiptLineID,CONVERT(int,0) As CurrentLabel,CONVERT(int,0) As TotalLabels insert into #UReceiptLabel from ReceiptLines WHERE 0=1
OPEN LabelsCursor
FETCH NEXT FROM LabelsCursor INTO #rmlReceiptID, #rmlReceiptLineID, #urmlNOofLabels
WHILE ##FETCH_STATUS = 0
BEGIN
SET #nloop = 0
SET #nLabels = #urmlNOofLabels
IF #nLabels < 1
SET #nLabels = 1
WHILE (#nloop < #nLabels)
BEGIN
SET #nloop = #nloop + 1
INSERT INTO #UReceiptLabel (rmlReceiptID, rmlReceiptLineID, CurrentLabel, TotalLabels) VALUES (#rmlReceiptID, #rmlReceiptLineID, #nloop, #nLabels)
END
FETCH NEXT FROM LabelsCursor INTO #rmlReceiptID, #rmlReceiptLineID, #urmlNOofLabels
END
CLOSE LabelsCursor
DEALLOCATE LabelsCursor
SET NOCOUNT OFF
SELECT CurrentLabel, TotalLabels, ReceiptLines.rmlReceiptID, ReceiptLines.rmlReceiptLineID, rmlJobID, rmlPartID, rmlJobQuantityReceived, urmlNoOfLabels, urmlQtyInABox, urmlLocation,rmpSupplierOrganizationID, cmoName, rmlDescription, rmlJobAssemblyID
FROM #UReceiptLabel
INNER JOIN ReceiptLines ON ReceiptLines.rmlReceiptID = #UReceiptLabel.rmlReceiptID and ReceiptLines.rmlReceiptLineID = #UReceiptLabel.rmlReceiptLineID
LEFT OUTER JOIN Receipts ON rmpReceiptID = #UReceiptLabel.rmlReceiptID
LEFT OUTER JOIN Organizations On rmpSupplierOrganizationID=cmoOrganizationID ORDER BY #UReceiptLabel.rmlReceiptID,#UReceiptLabel.rmlReceiptLineID,CurrentLabel
DROP TABLE #UReceiptLabel
when i attempt to run the crystal report i get An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name.
I would expect the crystal report to parse the input data and fill the label with appropriate information and print the correct number of labels.

T-SQL While Infinite Loop

The goal of the below script is to delete all records in a table for all the distinct users on it except the two first records for each user.
The thing is that the script goes into an infinite loop between these two lines
WHILE ##FETCH_STATUS = 0
SET #Event = 0;
The complete script is
DECLARE #Event int, #User int;
DECLARE cUsers CURSOR STATIC LOCAL FOR SELECT DISTINCT(UserID) FROM Identifications;
OPEN cUsers
FETCH NEXT FROM cUsers INTO #User;
WHILE ##FETCH_STATUS = 0
SET #Event = 0;
BEGIN
DECLARE cRows CURSOR STATIC LOCAL FOR
SELECT EventIdentificacionId FROM Identifications WHERE UserId = #User AND EventIdentificacionId NOT IN
(SELECT TOP 2 EventIdentificacionId FROM Identifications WHERE UserId = #User ORDER BY EventIdentificacionId);
OPEN cRows
FETCH NEXT FROM cRows INTO #Event;
WHILE ##FETCH_STATUS = 0
BEGIN
DELETE FROM Identifications WHERE EventIdentificacionId = #Event;
FETCH NEXT FROM cRows INTO #Event;
END
CLOSE cRows;
DEALLOCATE cRows;
FETCH NEXT FROM cUsers INTO #User;
END
CLOSE cUsers;
DEALLOCATE cUsers;
Can anybody give me some solution/explanation please?
As I wrote in my comment, There are far better ways to do such a thing than using a cursor, let alone a couple of nested cursors.
One such better option is to use a common table expression and row_number, and then delete the rows directly from the common table expression.
I'm not entirely sure this code is correct because I have no real way to test it as you didn't provide sample data or desired results, but I came up with that based on the code in the question:
;WITH CTE AS
(
SELECT UserId,
EventIdentificacionId,
ROW_NUMBER() OVER(PARTITION BY UserId ORDER BY EventIdentificacionId) As Rn
FROM Identifications
)
DELETE
FROM CTE
WHERE Rn > 2 -- Delete all but the first two rows
Change this line as shown:
DECLARE #Event int = 0, #User int = 0;
And remove this line
SET #Event = 0;
The reason you have an infinite loop is that this code:
WHILE ##FETCH_STATUS = 0
SET #Event = 0;
BEGIN
Is actually this:
-- A loop of a single instruction, with no exit criteria
WHILE ##FETCH_STATUS = 0 SET #Event = 0;
-- begin a new code block, with no condition or loop
BEGIN

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.

Trigger not working when inserting multiple records

I have the following trigger working correctly when I insert one record on table Pedidos.
However, when I insert multiple records I get a 512 error message. I've searched around for details about inserting multiple records and triggers, but not found an answer to my problem.
The trigger reads the inserted records and finds values from other tables to modify the value of the column situacion in table planificaciones.
Am I totally wrong in the way I'm trying to do this? Is there any obvious problems in my trigger?
CREATE TRIGGER TRG_INS_PL_SYNC_STATUS_PLA ON dbo.pedidos after insert as begin if ##ROWCOUNT = 0
return
set nocount on
declare #v_idpla int,
#v_situacion nvarchar(12),
#v_nombre nvarchar(50),
#v_almacen nvarchar(50),
#v_status_pedido nvarchar(4);
set #v_almacen = (select almacen_pedido from inserted);
set #v_nombre =(select cliente from inserted);
set #v_status_pedido = (select status_pedido from inserted);
set #v_situacion = (select top 1 nombre from dbo.StatusPlanificacion
where STATUS_PEDIDO = #v_status_pedido);
set #v_idpla = (select top 1 id from dbo.Planificaciones
where dia_entrega >= GETDATE() and situacion <> 'Departed'
and nombre like '%'+#v_almacen +'%'+ #v_nombre);
if(#v_idpla is not null)
begin
--select Timespan=SYSDATETIME() from inserted;
select ##rowcount;
UPDATE DBO.Planificaciones
SET situacion = #v_situacion
WHERE id = #v_idpla;
end
end
UPDATE & SOLVED: Looking on tanner suggestion i do the next update on code and works, but i think some one can find this more clear and useful. In suggested by tanner, says cursor not best way to do this and the best option is a Join. In my case this insert never goes more than 50 inserts at same time.
CREATE TRIGGER TRG_INS_PL_SYNC_STATUS_PLA
ON dbo.pedidos
after insert as
begin
declare #v_idpla int,#v_situacion nvarchar(12),#v_nombre nvarchar(50),#v_almacen nvarchar(50), #v_status_pedido nvarchar(4)
DECLARE c_cursor CURSOR FAST_FORWARD FOR SELECT ALMACEN_PEDIDO, CLIENTE, STATUS_PEDIDO FROM INSERTED;
OPEN c_cursor
fetch next from c_cursor into #v_almacen,#v_nombre,#v_status_pedido
--declared and open cursor chargin values to variables
while ##fetch_status = 0
begin
-- set values to variables from anothers tables
set #v_situacion = (select top 1 nombre from dbo.StatusPlanificacion where STATUS_PEDIDO = #v_status_pedido);
set #v_idpla = (select top 1 id from dbo.Planificaciones where dia_entrega >= GETDATE() and
situacion <> 'Departed' and nombre like '%'+#v_almacen +'%'+ #v_nombre);
--check value not null for assigned variable and do update to the value
if(#v_idpla is not null)
begin
UPDATE DBO.Planificaciones
SET situacion = #v_situacion
WHERE id = #v_idpla;
end
--move to the next row of cursor
fetch next from c_cursor into #v_almacen,#v_nombre,#v_status_pedido
end
CLOSE c_cursor
DEALLOCATE c_cursor
end
Not sure if the code is 100% correct but should give you an idea..
inserted is a dataset with all rows of that batch. You just need to think as set based operation.
CREATE TRIGGER TRG_INS_PL_SYNC_STATUS_PLA
ON dbo.pedidos
AFTER INSERT
AS
BEGIN
UPDATE p
SET
situacion = i.nombre
FROM DBO.Planificaciones p
INNER JOIN (
SELECT
v_idpla.id
v_situacion.nombre
FROM INSERTED I
CROSS APPLY (
select top 1
SP.nombre
from dbo.StatusPlanificacion SP
where
SP.STATUS_PEDIDO = I.STATUS_PEDIDO
) v_situacion
CROSS APPLY (
select top 1
Pla.id
from dbo.Planificaciones Pla
where
Pla.dia_entrega >= GETDATE() and
Pla.situacion <> 'Departed' and
Pla.nombre like '%'+I.ALMACEN_PEDIDO +'%'+ I.CLIENTE
) v_idpla
) I ON
P.id = I.id
END

Only one expression can be specified in the select list when the subquery is not introduced with EXISTS error

i am trying to create sql server procedure with if statement.
i am new to the ms sql server however i tried with the following statements but it gave me the below error Msg 116, Level 16, State 1, Procedure te, Line 9
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
here is the code i wrote
CREATE PROCEDURE test as
BEGIN
SET NOCOUNT ON;
if (select COUNT(load),load,contractor_id from [test].[dbo].[cont]
group by load,contractor_id
having load = (select MIN(load)from [test].[dbo].[cont])
) > 1
begin
SELECT top 1 COUNT(*),load ,contractor_id,name
FROM [test].[dbo].[cont]
group by load,contractor_id,name
having load = (select MIN(load)from [test].[dbo].[cont])
ORDER BY NEWID()
end
ELSE
BEGIN
SELECT top 1 COUNT(*),load ,contractor_id,name
FROM [test].[dbo].[cont]
group by load,contractor_id,name
having load = (select MIN(load)from [test].[dbo].[cont])
END
END
GO
can anyone help please
As the error says you cannot have multiple column selected when you use IF condition. In your first IF condition you are selecting multiple columns, however if conditions requires to have a query that can lead to one value. Other option is you have to use IF EXISTS, that can check count >1 as below
IF (SELECT COUNT(load),load,contractor_id
FROM [test].[dbo].[cont]
GROUP BY load,contractor_id
HAVING load = (SELECT MIN(load)
FROM [test].[dbo].[cont])
AND COUNT(load) >1)
Another thing what I noticed is you are excecuting the query which calculates the min of load multiple times. You can avoid that by storing it in a variable and use it further.
I have modified the procedure as below. Check if this works or not.
CREATE PROCEDURE test as
BEGIN
SET NOCOUNT ON;
DECLARE #count INT
DECLARE #minload INT
SELECT #minload = MIN(load)from [test].[dbo].[cont]
SELECT #count = COUNT(load) from [test].[dbo].[cont]
GROUP BY load,contractor_id
HAVING load = #minload
IF (#count) > 1
BEGIN
SELECT top 1 COUNT(*),load ,contractor_id,name
FROM [test].[dbo].[cont]
WHERE load = #minload
GROUP BY load,contractor_id,name
ORDER BY NEWID()
END
ELSE
BEGIN
SELECT top 1 COUNT(*),load ,contractor_id,name
FROM [test].[dbo].[cont]
GROUP BY load,contractor_id,name
HAVING load = #minload
END
END
UPDATE
Based on your comments, I suppose you can get the result with one simple query as below.
;WITH minLoad(load)
AS
(
SELECT MIN(load)
FROM [test].[dbo].[cont]
)
SELECT TOP 1 COUNT(*),c.load ,c.contractor_id,c.name
FROM [test].[dbo].[cont] c, minLoad
WHERE c.load = minLoad.load
ORDER BY NEWID();

Resources