IF statement in SQL Server stored procedure - sql-server

I have the following stored procedure:
ALTER PROCEDURE [dbo].[sp_Detail]
#ReceiptNumber int
AS
BEGIN
SET NOCOUNT ON;
WITH invoiceT AS
(SELECT
fs_transaksie.enti AS Entity,
fs_transaksie.rek AS Account,
fs_transaksie.trans_tipe AS TransactionType,
fs_transaksie.verwysnr AS ReferenceNumber
FROM mf_history.dbo.fs_transaksie
WHERE ( fs_transaksie.verwysnr = #ReceiptNumber ) AND (fs_transaksie.trans_tipe = 3))
, transactionT as
(SELECT
fs_kwitansie.kwitansienr AS InvoiceNumber,
fs_kwitansie.ktkaart_nr AS CreditCardNumber,
fs_kwitansie.ktkaart_bank AS CCBank,
fs_kwitansie.ktkaart_bedrag AS CCAmount
FROM mf_history.dbo.fs_kwitansie
WHERE ( fs_kwitansie.kwitansienr = #ReceiptNumber )
)
select *
from invoiceT
full outer join transactionT on invoiceT.ReferenceNumber = transactionT.InvoiceNumber
END
If the fs_transaksie.trans_tipe field = 3 and fs_transaksie.rek = 5205 then an error message needs to be displayed to the user. He may NOT view the data

If you can just not display the data, rather than raising an error then changing your WHERE clause to:
WHERE ( fs_transaksie.verwysnr = #ReceiptNumber ) AND (fs_transaksie.trans_tipe = 3)
And (fs_transaksie.rek != 5205)
should exclude it - you are already filtering it to just be trans_tipe = 3 so adding the And (fs_transaksie.rek != 5205) will exclude any where the results are 3 and 5205 respectively.

Related

Output clause of merge within a stored procedure

I'm trying create a stored procedure that contains a merge clause and want save output clause to a table (logs.ProductTaxProfileLog).
In my search for information I do not see that the output clause is used within the stored procedure
CREATE PROCEDURE dbo.sp_ProductTaxProfiles
AS
BEGIN
MERGE dbo.ProductTaxProfiles AS prd
USING staging.ProductTaxProfiles AS stg
ON stg.ProductTaxProfileId = prd.ProductTaxProfileId
-- UPDATE
WHEN MATCHED AND (
prd.ProductTaxProfileDescription <> stg.ProductTaxProfileDescription
OR prd.ProductIvaConditionId <> stg.ProductIvaConditionId
OR prd.ProductIvaConditionDescription <> stg.ProductIvaConditionDescription
OR prd.ProductIibbConditionId <> stg.ProductIibbConditionId
OR prd.ProductIibbConditionDescription <> stg.ProductIibbConditionDescription
OR prd.ProductInternalTaxConditionId <> stg.ProductInternalTaxConditionId
OR prd.ProductInternalTaxConditionDescription <> stg.ProductInternalTaxConditionDescription
OR prd.McActive <> stg.McActive
) THEN
UPDATE
SET
prd.ProductTaxProfileDescription = stg.ProductTaxProfileDescription,
prd.ProductIvaConditionId = stg.ProductIvaConditionId,
prd.ProductIvaConditionDescription = stg.ProductIvaConditionDescription,
prd.ProductIibbConditionId = stg.ProductIibbConditionId,
prd.ProductIibbConditionDescription = stg.ProductIibbConditionDescription,
prd.ProductInternalTaxConditionId = stg.ProductInternalTaxConditionId,
prd.ProductInternalTaxConditionDescription = stg.ProductInternalTaxConditionDescription,
prd.McActive = 1,
prd.UpdatedDate = CURRENT_TIMESTAMP
-- INSERT
WHEN NOT MATCHED BY TARGET THEN
INSERT (
ProductTaxProfileId
,ProductTaxProfileDescription
,ProductIvaConditionId
,ProductIvaConditionDescription
,ProductIibbConditionId
,ProductIibbConditionDescription
,ProductInternalTaxConditionId
,ProductInternalTaxConditionDescription
,McActive
,CreatedDate
,UpdatedDate
,DeletedDate
)
VALUES (
stg.ProductTaxProfileId
,stg.ProductTaxProfileDescription
,stg.ProductIvaConditionId
,stg.ProductIvaConditionDescription
,stg.ProductIibbConditionId
,stg.ProductIibbConditionDescription
,stg.ProductInternalTaxConditionId
,stg.ProductInternalTaxConditionDescription
,1
,CURRENT_TIMESTAMP
,CURRENT_TIMESTAMP
,NULL
)
-- DELETE
WHEN NOT MATCHED BY SOURCE AND (prd.McActive <> 0) THEN
UPDATE
SET
prd.McActive = 0
,prd.DeletedDate = CURRENT_TIMESTAMP
OUTPUT
CASE
WHEN $action = 'UPDATE' AND inserted.McActive = 0 AND deleted.McActive = 1 THEN 'DELETE'
WHEN $action = 'UPDATE' AND inserted.McActive = 1 AND deleted.McActive = 1 THEN 'UPDATE'
WHEN $action = 'INSERT' AND inserted.McActive = 1 AND COALESCE(deleted.McActive,0) = 0 THEN 'INSERT'
WHEN $action = 'UPDATE' AND inserted.McActive = 1 AND COALESCE(deleted.McActive,0) = 0 THEN 'RE-INSERT'
END AS ActionType,
inserted.*,
deleted.*
INTO logs.ProductTaxProfileLog;
END
GO
But I got this error:
Can anyone help me? I know that merge clause needs a semicolon at the end, but I really don't know how fix this error.
Finally Find the answer.
I was working with dbeaver and for some reason got that error. But when you run it from SSMS (SQL Server Management Studio) it runs fine, and everything works.
In conclusion the problem was the IDE

SQL stored procedure to update a table column by calculating the difference from 2 other tables

I have 3 tables in SQL Server that are exactly the same. I am trying to write a stored procedure to get the value of 2 columns from 2 tables and update the 3rd table with the difference. These are the 3 tables:
Current
Proposed
Final
I am passing in rfds_processing_id. It is similar to an order number and contains multiple rows, so matching has to be done on rfds_processing_id, type, sector, and position.
I need to match every row from the 3 tables and then subtract the value of Current.qty from Final.qty and update the Proposed.qty with the difference. It also needs to update Proposed.model with the value of Final.model (when Proposed.qty > 0). Currently it is setting every row to the same value. I'm assuming I need to loop through the rows. What should that look like?
ALTER PROCEDURE [dbo].[CalculateProposedAntennas]
(
#rfds_processing_id uniqueidentifier = null,
#id uniqueidentifier OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
UPDATE P
SET qty = (F.qty - C.qty) , model = F.model
FROM Proposed_Antenna P
INNER JOIN Final_Antenna F
ON P.rfds_processing_id = F.rfds_processing_id
INNER JOIN Current_Antenna C
ON F.rfds_processing_id = C.rfds_processing_id
WHERE
F.rfds_processing_id = C.rfds_processing_id
AND F.sector = C.sector
AND F.type = C.type
AND F.position = C.position
RETURN
END
The following query should do what you want:
ALTER PROCEDURE [dbo].[CalculateProposedAntennas]
(
#rfds_processing_id uniqueidentifier = null,
#id uniqueidentifier OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
UPDATE P
SET P.qty = F.qty - C.qty
,P.model = CASE WHEN Proposed.qty > 0 THEN F.model ELSE NULL END
FROM Proposed_Antenna P
INNER JOIN Final_Antenna F
ON F.rfds_processing_id = P.rfds_processing_id AND F.sector = P.sector AND F.type = P.type AND F.position = P.position
INNER JOIN Current_Antenna C
ON C.rfds_processing_id = P.rfds_processing_id AND C.sector = P.sector AND C.type = P.type AND C.position = P.position
RETURN
END
I highly recommend you to create a [UID] column in all three of your tables - the unique identifier case can be generated as below, the generated key is of varbinary type which is far better than string comparison in joins
select [UID] = HashBytes('MD5',rfds_processing_id+type+sector+position)

Stored procedure error: Msg 512, Level 16, State 1, Procedure sp_ActFTC, Line 64 Subquery returned more than 1 value

After executing a stored procedure, I get the following error:
Msg 512, Level 16, State 1, Procedure sp_ActFTC, Line 64
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I have two tables in the database, FTC_Alt and FichaTecnicaComp, and I need to update the FichaTecnicaComp table on a given date.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_ActFTC]
AS
DECLARE #Codigo NVARCHAR(20),
#DataAlteracao DATE,
#Categoria NVARCHAR(20),
#catord INT,
#SubCategoria NVARCHAR(255),
#subcatord INT,
#Ordem INT,
#CodigoComp NVARCHAR(10),
#DesignacaoComp NVARCHAR(50),
#QuantidadeComp NVARCHAR(25),
#UnidadeComp NVARCHAR(5),
#intRowCount INT,
#upAction NVARCHAR(255);
SELECT #Codigo = ft_alt.codigo
FROM ft_alt;
SELECT #DataAlteracao = ft_alt.dataalteracao
FROM ft_alt;
SELECT Categoria = ftc_alt.categoria
FROM ftc_alt;
SELECT catord = ftc_alt.catord
FROM ftc_alt;
SELECT SubCategoria = ftc_alt.subcategoria
FROM ftc_alt;
SELECT subcatord = ftc_alt.subcatord
FROM ftc_alt;
SELECT Ordem = ftc_alt.ordem
FROM ftc_alt;
SELECT CodigoComp = ftc_alt.codigocomp
FROM ftc_alt;
SELECT DesignacaoComp = ftc_alt.designacaocomp
FROM ftc_alt;
SELECT QuantidadeComp = ftc_alt.quantidadecomp
FROM ftc_alt;
SELECT UnidadeComp = ftc_alt.unidadecomp
FROM ftc_alt;
SELECT #intRowCount = ##RowCount;
SET #upAction = 'Composição nutricional actualizada/alterada'
BEGIN
IF (#DataAlteracao = (SELECT CONVERT(DATE, GETDATE())))
BEGIN
SET NOCOUNT ON
UPDATE [dbo].[FichaTecnicaComp]
SET [Codigo] = #Codigo,
[DataAlteracao] = #DataAlteracao,
categoria = ftc_alt.categoria,
catord = ftc_alt.catord,
subcategoria = ftc_alt.subcategoria,
subcatord = ftc_alt.subcatord,
ordem = ftc_alt.ordem,
codigocomp = ftc_alt.codigocomp,
designacaocomp = ftc_alt.designacaocomp,
quantidadecomp = ftc_alt.quantidadecomp,
unidadecomp = ftc_alt.unidadecomp
FROM [dbo].[FichaTecnicaComp]
JOIN ftc_alt ON [dbo].[FichaTecnicaComp].[Codigo] = (SELECT ft_alt.codigo
FROM ft_alt)
AND [dbo].[FichaTecnicaComp].Ordem = (SELECT FTC_Alt.Ordem
FROM FTC_Alt)
END
END
he expected result is that data in FichaTecnicaComp is updated from FTC_Alt.
Which doesn't happen.
It should be noted that the FichaTecnicaComp has the following working triggers: insertion, update and delete.
If you need the code of those triggers just ask.
Sub queries used in this context can only return a single value, whereas your sub queries are just returning all values of the Ordem and codigo columns. Use the columns directly in the ON clause instead of as sub-selects. You will also want use aliases instead of the full table names. Using only the keyword JOIN will default to an INNER JOIN, which is what I'm assuming you intend to use, however explicitly stating this will help with readability. The first sub query in your post uses ft_alt, instead of ftc_alt, but since this is the only reference to this table I'm guessing this is a typo?
BEGIN
SET NOCOUNT ON
UPDATE FTC
SET
FTC.[Codigo] = FT.Codigo,
FTC.[DataAlteracao] = FT.dataalteracao,
FTC.categoria = ALT.categoria,
FTC.catord = ALT.catord,
FTC.subcategoria = ALT.subcategoria,
FTC.subcatord = ALT.subcatord,
FTC.ordem = ALT.ordem,
FTC.codigocomp = ALT.codigocomp,
FTC.designacaocomp = ALT.designacaocomp,
FTC.quantidadecomp = ALT.quantidadecomp,
FTC.unidadecomp = ALT.unidadecomp
FROM [dbo].[FichaTecnicaComp] FTC
INNER JOIN ft_alt FT ON FTC.Codig = FT.Codigo
INNER JOIN ftc_alt ALT ON FTC.Ordem = ALT.Ordem
END
The error message itself says that one of the sub queries used in this stored procedure returns more than one record, while your update statement can handle only one returned row the way it is written. If you run below queries one by one, you will know where is the problem. Either you need to fix the subquery or may need to use IN instead of = in main query. I hope that helps.
(SELECT ft_alt.codigo
FROM ft_alt)
AND
[dbo].[FichaTecnicaComp].Ordem =
(SELECT FTC_Alt.Ordem
FROM FTC_Alt
And also run below independently.
SELECT FTC_Alt.Ordem
FROM FTC_Alt

Subquery returned more than 1 value when trigger executes

I have a trigger which adds a log entry into a table upon a field change in another table. it works when one row is changed but errors when multiple rows re changed. Anyone out there able to explain what I have to do to get my trigger working also for multi row updates?
Many thanks,
Derek
Declare #PropertyID uniqueidentifier
Set #PropertyID = (Select CONVERT(VARCHAR( 36 ), ISNULL(i.[PropertyPK], d.[PropertyPK]))
FROM
INSERTED i
FULL OUTER JOIN DELETED d ON ( d.[PropertyPK] = i.[PropertyPK] )
WHERE
( d.[strManagingOfficeName] <> i.[strManagingOfficeName] ) OR
( d.[strManagingOfficeName] IS NULL AND i.[strManagingOfficeName] IS NOT NULL ) OR
( i.[strManagingOfficeName] IS NULL AND d.[strManagingOfficeName] IS NOT NULL ))
Declare #CompanyID uniqueidentifier
Set #CompanyID = (Select CompanyFK From Property Where PropertyPK = #PropertyID)
--Deleted Old Ones
Delete From TDSAPILog Where ObjectFK = #PropertyID And strObject = 'Branch Change'
--Insert New Log
INSERT dbo.TDSAPILog(TDSAPILogPK, ObjectFK, strObject, strStatus, CompanyFK, dteDateLogged)
SELECT
NewID(),
#PropertyID,
'Branch Change',
'Active',
#CompanyID ,
GetDate()
This error occur when you return more than 1 value from a query and save in a variable or compare with a value in where clause.
In your example I think the error occur at this line
SET #CompanyID = (SELECT CompanyFK FROM Property WHERE PropertyPK = #PropertyID)
To resolve the reported error just put "TOP 1" in your query. Example is shown here:
SET #CompanyID = (SELECT TOP 1 CompanyFK FROM Property WHERE PropertyPK = #PropertyID)
Subquery returned more than 1 value error may occur at the following scenarios:
SET #YouVariable = (SELECT ColumnID FROM yourTable WHERE Identity = #SomeValue)
-- if the above query return more than 1 value the same error will be occurred
-- to resolve this problem just put "TOP 1" before ColumnID
SELECT *
FROM OtherTable
WHERE OtherIdentity = ((SELECT ColumnID FROM yourTable
WHERE Identity = #SomeValue))
-- if the above query return more than 1 value the same error will be occurred
-- to resolve this problem just replace "= with IN()". Example give below
SELECT *
FROM OtherTable
WHERE OtherIdentity IN ((SELECT ColumnID FROM yourTable
WHERE Identity = #SomeValue))

Too Many Rows Were Affected error on updating a Transact SQL linked table

I am trying to update a linked table with this...
update openquery (LINKSERVERID, 'select tng_email from user_list where tng_id = 62873')
set tng_email = 'blah#blah.com';
... but I get the following error ...
OLE DB provider "MSDASQL" for linked server "LINKSERVERID" returned message "Key column information is insufficient or incorrect.
Too many rows were affected by update.".
FYI: tng_id is the primary key.
How do I fix?
I think you need to include the key in the select query, so try this:
update openquery(
LINKSERVERID, 'select tng_id, tng_email from user_list where tng_id = 62873'
) set tng_email = 'blah#blah.com';
I tried the answer above from jpw, but it didn't work for me.
I developed a trigger of which I also received the same error using the code below:
begin
if TRIGGER_NESTLEVEL() > 1
return
declare #JCid int = (select top 1 iJCMasterID from inserted)
begin
update L set uiJCTxCMLineNumber = NewLineNum
from (
select
rank() over (order by idJCTxLines) NewLineNum
, iJCMasterID
, uiJCTxCMLineNumber
, idJCTxLines
from _btblJCTxLines
where iJCMasterID = #JCid
) L
where iJCMasterID = #JCid
end
end
go
However, I resolved it by changing it to :
begin
if TRIGGER_NESTLEVEL() > 1
return
declare #JCid int = (select top 1 iJCMasterID from inserted)
begin
update L set uiJCTxCMLineNumber = NewLineNum
from (
select
rank() over (order by idJCTxLines) NewLineNum
, iJCMasterID
, uiJCTxCMLineNumber
, idJCTxLines
from _btblJCTxLines
where iJCMasterID = #JCid
) L
join inserted i on L.idJCTxLines = i.idJCTxLines
end
end
go
Hope this helps.
I solved this error by adding a unique index to the underlying table.

Resources