SQL Server self-update TRUNCATE value using ISNULL - sql-server

I do not know if this is a bug.
I found that when this code is run the value in column MyComments is truncated to the first letter. It seems to be related to the declaration of variable #MYComments, cause after I changed the declaration to VARCHAR(MAX) it worked, but what seems to be weird for me is that if no value is set to variable #MYComments function ISNULL(#MYComments, MYComments) invocation should returns the current value.
DECLARE #MYComments AS VARCHAR
UPDATE [dbo].[TestIssue]
SET MYComments = ISNULL(#MYComments,MYComments)
I was able to reproduce this using this script.
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.TestIssue
(
id int NOT NULL,
MYComments varchar(MAX) NOT NULL
) ON [PRIMARY]
TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE dbo.TestIssue SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
select Has_Perms_By_Name(N'dbo.TestIssue', 'Object', 'ALTER') as ALT_Per, Has_Perms_By_Name(N'dbo.TestIssue', 'Object', 'VIEW DEFINITION') as View_def_Per, Has_Perms_By_Name(N'dbo.TestIssue', 'Object', 'CONTROL') as Contr_Per
INSERT INTO [dbo].[TestIssue]
([id]
,[MYComments])
VALUES
(1
,'MY COMMENT 1')
GO
SELECT * FROM [dbo].[TestIssue]
DECLARE #MYComments AS VARCHAR
UPDATE [dbo].[TestIssue]
SET MYComments = ISNULL(#MYComments,MYComments)
SELECT * FROM [dbo].[TestIssue]

Your problem is with declararion:
Declare #Mycomments VARCHAR
This declaration means that is 1 char long, so return of ISNULL should be also 1 char long. Change declarstion to VARCHAR(MAX). It solve your problem.

Related

Fire SQL Trigger When Column Value Changes

I am adding the date to a column in SQL when the 'workstatus' is 'completed', but my problem is, when I open and save the same job again in the software, it runs the trigger and changes the date again to a new value which I don't want.
I want the trigger to run only if the 'workstatus' value is something else than 'completed'.
GO
/****** Object: Trigger [dbo].[TRJCD_JOBREQUEST] Script Date: 06/25/2021 15:49:04 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TRJCD_JOBREQUEST] ON [dbo].[TBL_JOBREQUEST]
AFTER UPDATE,INSERT
AS
if (Update (workstatus))
begin
DECLARE #Jobcompletiondate datetime
DECLARE #workstatus VARCHAR(15)
DECLARE #jobid int
select #workstatus = workstatus from inserted
select #jobid = jobid from inserted
select #Jobcompletiondate = GETDATE()
begin
if #workstatus='Completed'
update TBL_JOBREQUEST set JobCompDate=#Jobcompletiondate where jobid = #jobid
end
end
The following is how you should construct your trigger.
There is no need to assign any values to variables, triggers fire once per batch and always operate on the set of updated rows.
If you update a status to Completed you need to check it's not currently Completed, also if you want to retain the first JobCompDate even if the status is amended afterwards simply use a case expression to only update the column where it's currently NULL.
create or alter trigger [dbo].[TRJCD_JOBREQUEST] on [dbo].[TBL_JOBREQUEST]
after update,insert
as
if ##RowCount=0 return
set nocount on
if Update (workstatus)
begin
update t set
t.JobCompDate=case when t.JobCompDate is null then GetDate() else t.JobCompDate end
from inserted i join TBL_JOBREQUEST t on t.jobid=i.jobid
where i.workstatus='Completed'
and not exists (
select * from deleted d
where d.jobid=i.jobid and d.workstatus=i.workstatus
)
end
Please note that I do not have your data set, so I'm unable to test the trigger, however, based on what you provided in your question, I believe this is the answer you are seeking:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TRJCD_JOBREQUEST] ON [dbo].[TBL_JOBREQUEST]
AFTER UPDATE,INSERT
AS
if (Update (workstatus))
begin
DECLARE #Jobcompletiondate datetime
DECLARE #currentworkstatus VARCHAR(15)
DECLARE #oldworkstatus VARCHAR(15)
DECLARE #jobid int
select #oldworkstatus = workstatus from deleted
select #currentworkstatus = workstatus from inserted
select #jobid = jobid from inserted
select #Jobcompletiondate = GETDATE()
begin
if #currentworkstatus='Completed' and #oldworkstatus <> 'Completed'
update TBL_JOBREQUEST set JobCompDate=#Jobcompletiondate where jobid = #jobid
end
end
You needed to check if the deleted workstatus does not equal Completed and only then should the trigger fire.

Heterogeneous queries require the ANSI_NULLS and ANSI_WARNINGS - Trigger dealing with linked server

Upon trying to insert into table via app, I receive following error message.
Heterogeneous queries require the ANSI_NULLS and ANSI_WARNINGS options to be set for the connection.
Neither ANSI_NULLS ON nor ANSI_WARNINGS ON did help...
SET ANSI_NULLS ON
GO
SET ANSI_WARNINGS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[BenRef_UPDATE]
ON [dbo].[ITRAEN]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON
IF UPDATE(poz2)
CREATE TABLE storeBenRef(
BeneficiaryRef VARCHAR(30),
Partija VARCHAR(30) collate Serbian_Latin_100_CI_AS,
Datum DATETIME
);
INSERT INTO storeBenRef ( BeneficiaryRef, Partija, Datum )
SELECT i.poz2, i.PARTIJA,i.DOTVORANJE
FROM inserted i
INNER JOIN deleted d
ON i.PARTIJA = d.PARTIJA;
SET ANSI_NULLS ON
SET ANSI_WARNINGS ON
UPDATE [EXPSRV1].[OPR].[protected].[TransferServiceArrangement]
SET PaymentDetailsBeneficiaryReferenceNumber = tmp.BeneficiaryRef
FROM storeBenRef tmp
INNER JOIN [EXPSRV1].[OPR].[protected].[TransferServiceArrangement]
trsa
ON trsa.PaymentDetailsPayerAccountNumber = tmp.partija
WHERE trsa.FirstPaymentDate = tmp.Datum
DROP TABLE dbo.storeBenRef;
SET NOCOUNT ON;
END;
Tried to put them before an update statement, tried to set them individually,
but it did not work.
I ask for help.

Don't Understand SQL Procedure Error

I have a master table "Repairs" and a detail table "RepairDetails" I am trying to write a procedure to update both tables when I send the appropriate parameters from my application. Here is my SQL:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[UpdateRepair]
#RepairID bigint,
#TypeID bigint = NULL,
#Directions nvarchar(3000) = NULL,
#NewDetails NewDetails READONLY
AS
BEGIN
SET NOCOUNT ON;
UPDATE Repairs
SET
TypeID = ISNULL(#TypeID, TypeID),
Directions = ISNULL(#Directions, Directions),
LastUpdate = SYSDATETIME()
WHERE RepairID = #RepairID;
IF #NewDetails IS NOT NULL UpdateRepairDetails;
END
where "NewDetails" is a User-defined table type and "UpdateRepairDetails" is a different stored procedure that takes #RepairID and #NewDetails as parameters.
I have an error and a question. The error message is:
Must declare the scalar variable "#NewDetails"
which I don't understand because it is defined.
And my question is: will the parameters "#RepairID" and "#NewDetails" get automatically passed to the "UpdateRepairDetails" procedure. If not, what is the proper approach to accomplish this?
You cannot assign NULL to a table variable. Hence you can't check whether a table variable is NULL.
Second: no. You should call as follows:
EXEC UpdateRepairDetails #RepairID, #NewDetails;

Must Declare Scalar variable on creating stored procedure

I am creating first time stored procedure but I don't know why this showing error. I also have many other post but didn't understand if someone can tell what I am doing wrong here.
Stored procedure:
SET ANSI_NULLS ON
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[DeleteOrganization]
#ORG_ID bigint
AS
BEGIN
SET NOCOUNT ON;
delete from Organizations where ORG_ID=#ORGID
delete from Institutes where INS_FK_ORGID=#ORGID
delete from Branches where BRN_ID=#ORGID
END
The variable is declared as #ORG_ID bigint with an underscore but you refer to it without the underscore: #ORGID. Pick one and use it consistently.
This should work:
ALTER PROCEDURE [dbo].[DeleteOrganization]
#ORGID bigint
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM Organizations WHERE ORG_ID = #ORGID
DELETE FROM Institutes WHERE INS_FK_ORGID = #ORGID
DELETE FROM Branches WHERE BRN_ID = #ORGID
END

Using UPDATE in stored procedure with optional parameters

I have an SP like so (using SQL Server):
ALTER PROCEDURE [dbo].[sp_ClientNotes_update]
#id uniqueidentifier,
#ordering smallint = NULL,
#title nvarchar(20) = NULL,
#content text = NULL
AS
BEGIN
SET NOCOUNT ON;
UPDATE tbl_ClientNotes
SET ordering=#ordering, title=#title, content=#content
WHERE id=#id
END
I would like to only set the values if they are passed into the SP, i.e. not NULL. Can this be done?
This question seems to suggest the only way is using completely separate queries with conditionals, but for 3 optional parameters this would obviously be a nightmare!
Try this.
ALTER PROCEDURE [dbo].[sp_ClientNotes_update]
#id uniqueidentifier,
#ordering smallint = NULL,
#title nvarchar(20) = NULL,
#content text = NULL
AS
BEGIN
SET NOCOUNT ON;
UPDATE tbl_ClientNotes
SET ordering=ISNULL(#ordering,ordering),
title=ISNULL(#title,title),
content=ISNULL(#content, content)
WHERE id=#id
END
It might also be worth adding an extra part to the WHERE clause, if you use transactional replication then it will send another update to the subscriber if all are NULL, to prevent this.
WHERE id=#id AND (#ordering IS NOT NULL OR
#title IS NOT NULL OR
#content IS NOT NULL)
UPDATE tbl_ClientNotes
SET
ordering=ISNULL#ordering,ordering),
title=isnull(#title,title),
content=isnull(#content,content)
WHERE id=#id
I think I remember seeing before that if you are updating to the same value SQL Server will actually recognize this and won't do an unnecessary write.
One Idea:
UPDATE tbl_ClientNotes
SET ordering=ISNULL(#ordering, ordering),
title=ISNULL(#title, title),
content=ISNULL(#content, content)
WHERE id=#id
UPDATE tbl_ClientNotes
SET ordering=#ordering, title=#title, content=#content
WHERE id=#id
AND #ordering IS NOT NULL
AND #title IS NOT NULL
AND #content IS NOT NULL
Or if you meant you only want to update individual columns you would use the post above mine. I read it as do not update if any values are null
ALTER PROCEDURE LN
(
#Firstname nvarchar(200)
)
AS
BEGIN
UPDATE tbl_Students1
SET Firstname=#Firstname
WHERE Studentid=3
END
exec LN 'Thanvi'

Resources