SQL Server - using variable in triggers - sql

I have a trigger set on a table to run after Insert and I want to query the incoming data with that already in the target table, then append a different message based on the changes identified.
Here's what I have so far
ALTER TRIGGER [dbo].[trg_Measure_Insert_Audit]
ON [dbo].[Measures_slave]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #message VARCHAR(MAX)
insert into aud_Measures
(
measure_FK,
[description],
oldname,
[newname],
milestone
)
select
i.measure_PK,
CASE
WHEN (SELECT TOP 1 measure_name FROM Measures_slave s WHERE s.slave_PK = i.slave_PK -1) <> i.measure_name THEN 'Measure Name Changed to <b> ' + i.measure_name + ' </b>'
END,
(SELECT TOP 1 measure_name FROM Measures_slave s WHERE s.slave_PK = i.slave_PK -1),
i.measure_name,
--'Test Audit Entry',
'Yes'
from
inserted i
END
I want to replace the CASE WHEN with a list of either IFs or WHENs that go down each field on both measure_slave and Inserted and append a message to #message if a difference is found.
I'm trying to achieve this, essentially:
select
i.measure_PK,
CASE
--WHEN (SELECT TOP 1 measure_name FROM Measures_slave s WHERE s.slave_PK = i.slave_PK -1) <> i.measure_name THEN 'Measure Name Changed to <b> ' + i.measure_name + ' </b>'
WHEN (SELECT TOP 1 measure_name FROM Measures_slave s WHERE s.slave_PK = i.slave_PK -1) <> i.measure_name SET #message = 'Measure Name Changed to <b> ' + i.measure_name + ' </b>'
WHEN (SELECT TOP 1 calculation_steps FROM Measures_slave s WHERE s.slave_PK = i.slave_PK -1) <> i.calculation_steps SET #message = #message + 'Steps changed to: <b> ' + i.calculation_steps + ' </b>'
END,
(SELECT TOP 1 measure_name FROM Measures_slave s WHERE s.slave_PK = i.slave_PK -1),
i.measure_name,
--'Test Audit Entry',
'Yes'
from
inserted i

I think you may be able to achive what you need without using a variable:
ALTER TRIGGER [dbo].[trg_Measure_Insert_Audit]
ON [dbo].[Measures_slave]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO aud_Measures
(
measure_FK,
[description],
oldname,
[newname],
milestone
)
SELECT
i.measure_PK,
CASE WHEN (i.measure_name <> s.measure_name) THEN 'Measure Name Changed to <b> ' + i.measure_name + ' </b>' ELSE '' END + -- The resulting value from this line concatenates with
CASE WHEN (i.calculation_steps <> s.calculation_steps ) THEN 'Steps changed to: <b> ' + i.calculation_steps + ' </b>' ELSE '' END, -- the resulting value from of this line
s.measure_name,
i.measure_name
'Yes'
FROM Inserted i LEFT JOIN Measures_slave s ON s.slave_PK = i.slave_PK -1
-- If you want to audit only the rows that in which there IS actually a difference in any of measure_name or calculation_steps columns, then use the following:
WHERE (i.measure_name <> s.measure_name) OR (i.calculation_steps <> s.calculation_steps )
END

Related

SQL Server stored proc substitute an empty string if column is empty or null

I need to check to see if a certain coloumn in my stored proc is either empty or null.
This is a snippet of what I have right now:
SELECT * ,
CASE WHEN a.USER IS NULL
THEN b.ROLE
ELSE ISNULL(a.FirstName,'') + ' ' + (ISNULL(a.MiddleName+' ','') + ISNULL(a.LastName,'')
END AS 'CustomerName'
I am checking to see if a.MiddleName is NULL but how do I also check to see if its empty and if its empty to just insert a empty string (no space)?
Thanks
Change to
SELECT
* ,
CASE
WHEN a.USER IS NULL
THEN b.ROLE
ELSE CASE
WHEN ISNULL(a.MiddleName, '') = ''
THEN ISNULL(a.FirstName,'') + ' ' + ISNULL(a.LastName,'')
ELSE ISNULL(a.FirstName,'') + ' ' + a.MiddleName + ' ' + ISNULL(a.LastName,'')
END
END AS 'CustomerName'
Another sollution is:
SELECT * ,
CASE WHEN a.USER IS NULL
THEN b.ROLE
ELSE ISNULL(a.FirstName,'') + replace( ( ' ' + ISNULL(a.MiddleName+' ',' '),' ',' ') + ISNULL(a.LastName,'')
END AS 'CustomerName'

MS SQL Stored Procedure run time error

How to rectify error in sp while concatenating the MSSQL queries?
SET #Ws_Sql = 'SELECT CONVERT(VARCHAR(25),#WS_STATUS) AS [Status],A.RECNUB AS [Rec #], A.REVCOD AS [Revenue CODE], '
IF #LNKOPT = 1
BEGIN
SET #Ws_Sql = #WS_SQL +''' AS [Status],'
END
ELSE IF #LNKOPT = 2
BEGIN
SET #Ws_Sql = #WS_SQL +'' + 'Modified' + ' AS [Status],'
END
ELSE IF #LNKOPT = 3
BEGIN
SET #Ws_Sql = #WS_SQL +'' + 'Deleted' + ' AS [Status],'
END
ELSE IF #LNKOPT = 4
BEGIN
SET #Ws_Sql = #WS_SQL +'' + 'Reprint' + ' AS [Status],'
END
Are you attempting to assign an empty value to the [Status] output column, in case #LNKOPT = 1?
In that case, you need to use double apostrophes, to escape the apostrophe character:
IF #LNKOPT = 1
BEGIN
SET #Ws_Sql = #WS_SQL +''''' AS [Status],'
END
which will result in #Ws_Sql containing: '' AS [Status] (otherwise it would result in ' AS [Status] which will give an error when the #Ws_Sql string is executed).

Trigger should be, but is not, recursive, right?

New to triggers and trying to figure out why the nested IF at the end of this of this trigger doesn't seem to be recursive. What I would like is for it to trigger itself over and over again until it hits a #ProcessStatus of 4. It only goes to 1. Not really sure why, any suggestions?
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[tr_ProcessRecord] ON [dbo].[_ShipMain]
FOR UPDATE
AS
BEGIN TRANSACTION
declare #cqID nvarchar(24),
#carrier nvarchar(24),
#shipCode nvarchar(24),
#Note nvarchar(255),
#ProcessStatus nvarchar(24);
SELECT #cqID = i.ConnectQueryID from inserted i;
SELECT #carrier = i.Carrier from inserted i;
SELECT #shipCode = i.ShipCode from inserted i;
SELECT #ProcessStatus = i.Status from inserted i;
SELECT #Note = 'ID: ' + #cqID + ' ' +
'Carrier: ' + ' ' + convert(nvarchar(24), #carrier) + ' ' +
'Ship Code: ' + #shipCode + ' ' +
(SELECT CASE #ProcessStatus
WHEN 0 THEN 'Recieved'
WHEN 1 THEN 'Processing'
WHEN 2 THEN 'More Processing'
WHEN 3 THEN 'Finishing'
WHEN 4 THEN 'Processed'
END);
INSERT INTO [_ShipLog]
SELECT #cqID
,GETDATE()
,#Note
,#ProcessStatus
IF #ProcessStatus = 0
BEGIN
UPDATE [_ShipMain]
SET [Status] = #ProcessStatus + 1
WHERE [ConnectQueryID] = #cqID;
END
IF #ProcessStatus = 1
BEGIN
UPDATE [_ShipMain]
SET [Status] = #ProcessStatus + 1
WHERE [ConnectQueryID] = #cqID;
END
IF #ProcessStatus = 2
BEGIN
UPDATE [_ShipMain]
SET [Status] = #ProcessStatus + 1
WHERE [ConnectQueryID] = #cqID;
END
IF #ProcessStatus = 3
BEGIN
UPDATE [_ShipMain]
SET [Status] = #ProcessStatus + 1
WHERE [ConnectQueryID] = #cqID;
END
COMMIT TRANSACTION
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[tr_ProcessRecord] ON [dbo].[_ShipMain]
FOR UPDATE
AS
BEGIN TRANSACTION
declare #cqID nvarchar(24),
#carrier nvarchar(24),
#shipCode nvarchar(24),
#Note nvarchar(255),
#ProcessStatus nvarchar(24);
SELECT
#cqID = i.ConnectQueryID
,#carrier = i.Carrier
,#shipCode = i.ShipCode
,#ProcessStatus = i.Status
from inserted i;
SELECT #Note = 'ID: ' + #cqID + ' ' +
'Carrier: ' + ' ' + convert(nvarchar(24), #carrier) + ' ' +
'Ship Code: ' + #shipCode + ' ' +
(SELECT CASE #ProcessStatus
WHEN 0 THEN 'Recieved'
WHEN 1 THEN 'Processing'
WHEN 2 THEN 'More Processing'
WHEN 3 THEN 'Finishing'
WHEN 4 THEN 'Processed'
END);
INSERT INTO [_ShipLog]
SELECT #cqID
,GETDATE()
,#Note
,#ProcessStatus
UPDATE [_ShipMain]
SET [Status] = #ProcessStatus + 1
WHERE [ConnectQueryID] = #cqID
and #ProcessStatus in (0,1,2,3)
COMMIT TRANSACTION

Can't put a second "with" statement into the query

I have a query - which is combining with a Union statement the 5 columns into 2 columns.
So basically - an ID + Some Information. As the ID could be in column 2-5 - several times... I rearranged to be everything in one ID column + the text.
Now - I wanted to use a second "with" statement - to combine the IDs of several rows - with a XML path. But here I got stuck.
That is the code - which gives me the two column - with content as expected:
With
STall as (Select
'Status: ' + ST.Status + Char(10) + 'Crew Information:' + Char(10) +
'Instructor: ' + ST.IP + Char(10) + 'Student: ' + ST.SP + Char(10) + Case
When ST.ACM1 = 'NA' Then '' Else 'ACM1: ' + ST.ACM1 + Char(10) End + Case
When ST.ACM2 = 'NA' Then '' Else 'ACM2: ' + ST.ACM2 + Char(10)
End + 'Lesson: ' + ST.Lesson + Char(10) + Case
When ST.ScheduleRemarks = '' Then ''
Else ' REM:' + ST.ScheduleRemarks + Char(10)
End + 'Equipment: ' + ST.EquipmentName + ' (' + ST.Callsign + ')' +
Char(10) + 'Start: ' + Convert(VARCHAR(10),ST.ScheduleTO,104) + ' - ' +
Convert(VARCHAR(5),ST.ScheduleTO,108) + ' UTC' + Char(10) + 'End: ' +
Convert(VARCHAR(10),ST.ScheduleTD,104) + ' - ' +
Convert(VARCHAR(5),ST.ScheduleTD,108) + ' UTC' + Char(10) + Case
When ST.ATC = 'NA' Then '' Else ST.ATC End As SInfo,
ST.IDIP,
ST.IDSP,
ST.IDA1,
ST.IDA2
From
(Select
Case When Schedule.StatusRelease = 1 Then 'OK' Else Case
When Schedule.StatusRequest = 1 Then 'STBY' Else 'N/A' End
End As Status,
Schedule.ContactIDIP,
Schedule.ContactIDSP,
MasterLesson.Lesson,
Equipment.EquipmentName,
CallSignList.Callsign,
Schedule.Meeting,
Schedule.ScheduleRemarks,
Schedule.StatusRelease,
Schedule.StatusRequest,
Schedule.ScheduleDay,
ContactList.FullNameTLC As IP,
ContactList1.FullNameTLC As SP,
Case When Schedule.ContactIDACM1 = 0 Then 'NA'
Else ContactList2.FullNameTLC End As ACM1,
Case When Schedule.ContactIDACM2 = 0 Then 'NA'
Else ContactList3.FullNameTLC End As ACM2,
Schedule.ScheduleTO,
Schedule.ScheduleTD,
Case When Schedule.RouteID = 0 Then 'NA'
Else 'Route: ' + Airport.ICAO + ' - ' + Case
When IsNull(Airport1.ICAO, 'NA') = 'NA' Then ' '
Else Airport1.ICAO + ' - ' End + Airport2.ICAO + Char(10) + Char(13)
End As ATC,
ContactList.Id As IDIP,
ContactList1.Id As IDSP,
ContactList2.Id As IDA1,
ContactList3.Id As IDA2
From
Schedule Inner Join
StudentLesson On Schedule.ScheduleLessonID = StudentLesson.StudentLessonID
Inner Join
MasterLesson On StudentLesson.LessonID = MasterLesson.ID Inner Join
Equipment On Schedule.EquipmentID = Equipment.ID Left Join
CallSignList On CallSignList.ID = Schedule.CallSignListID Left Join
Route On Route.ID = Schedule.RouteID Inner Join
ContactList On ContactList.Id = Schedule.ContactIDIP Inner Join
ContactList ContactList1 On ContactList1.Id = Schedule.ContactIDSP
Left Join
ContactList ContactList2 On Schedule.ContactIDACM1 = ContactList2.Id
Left Join
ContactList ContactList3 On Schedule.ContactIDACM2 = ContactList3.Id
Left Join
Airport On Route.AirportID_Dep = Airport.ID Left Join
Airport Airport1 On Route.AirportID_Via = Airport1.ID Left Join
Airport Airport2 On Route.AirportID_Arr = Airport2.ID
Where
((Schedule.StatusRelease = 1) Or
(Schedule.StatusRequest = 1)) And
Schedule.ScheduleDay = '21.02.2014') As ST)
Select Distinct
STall.IDIP,SInfo
From
STall
where STall.IDIP > 0
UNION
Select Distinct
STall.IDSP,SInfo
From
STall
where STall.IDSP > 0
UNION
Select Distinct
STall.IDA1,SInfo
From
STall
where STall.IDA1 > 0
UNION
Select Distinct
STall.IDA2,SInfo
From
STall
where STall.IDA2 > 0
Now - I tried to add another With STtotal as ( in the beginning...
and
)
Select Distinct
STsub.IDIP,
SubString((Select
+Char(10) + STn1.SInfo As [text()]
From
STsub STn1
Where
STn1.IDIP = STtotal.IDIP
Order By
STn1.IDIP
For Xml Path('')), 2, 1000) ScheduleInfo
From
STtotal
But I get an error - with wrong Statement at "with".
Maybe there is another approach - how to combine - the "Info Text" column with all IDs - which could be in column 2-5.
Thanks for any imput
Separate your CTEs with a comma; the WITH only needs to be specified once:
;WITH CTE1 AS (
...
), CTE2 AS (
...
)
SELECT ...
Did you remember to put a semi colon at the end of the first statement?

How to copy, replace, and insert across all rows in the database

I'll do my best to explain:
Copy all rows that exist in current database
Mass replace a specific string value in every row that contains a specific field
Insert the copied rows
Not sure what approach to take other than hammering out sql scripts.
Thanks!
Is this as simple as creating an Data Flow Source, selecting all the rows, then passing them to a Derived Column transformation, which would be along the lines of:
REPLACE( [ColumnName], "SpecificValue", "ReplacementValue" )
and then insert these rows into your destination table using the relevant Data Flow Destination.
I may be misunderstanding or simplifying step 2...
Assuming you have a table called "table2" and that table consists of the columns facilabbr, unitname, and sortnum... You can select all rows into a temporary table (# signifies a temporary table) changing the "unitname" column to something else...You'll be left with the new values in the temporary table. You can then replace the values in your initial table if you want.
INSERT INTO #temptable1
SELECT facilabbr,
'myNewUnitName' as unitname,
sortnum
FROM table2
DELETE FROM table2
INSERT INTO table2
SELECT facilabbr,
unitname,
sortnum
FROM #temptable1
--THIS QUERY IS ONLY EQUIPPED TO HANDLE:
--SIMPLE NUMERICS SUCH AS FLOATS, INTS, ETC
--SIMPLE STRING DATA TYPES LIMITED TO: VARCHARS, CHARS, NCHARS AND NVARCHARS
--DATES AND DATETIMES
Create Procedure SQLCloner
#TableName as VarChar(max), -- Table that holds data to clone.
#NewTableName as VarChar(max) = '', -- Table to Insert into. If same as Tablename leave blank or write ''.
#VarCharFind as VarChar(max) = '', -- Value to find (In order to replace). If you aren't replacing leave blank or write ''.
#VarCharReplace as VarChar(max) = '', -- Value to replace. If you aren't replacing leave blank or write ''.
#OptionalParam As VarChar(Max) = '' -- Your WHERE clause. If you have none leave blank or write ''.
AS
Declare #index as int = 1
Declare #rowcount As Int = 0
Declare #execFunction As VarChar(max) = ''
Declare #InsertTableRowName As VarChar(max) = ''
Declare #TempFilterType As VarChar(Max) = ''
--Create RowCount of Table
Select #ROWCOUNT = Count(*)
From (
Select Column_Name
From INFORMATION_SCHEMA.COLUMNS
Where Table_Name = '' + #TableName + ''
) As TheCount
--Use While Loop to create Table Columns
While #index <= #rowcount
Begin
--Determines the Variable type to change the exec function accordingly
Select #TempFilterType = TypeTable.DATA_TYPE
From (
Select Data_Type,
ROW_NUMBER() OVER (Order By Ordinal_Position) as RowNum
From INFORMATION_SCHEMA.COLUMNS
Where Table_Name = #TableName
) As TypeTable
Where TypeTable.RowNum = #index
--Prepares #InsertTableRowName With the first part of the string
Set #InsertTableRowName = Case
When #TempFilterType IN('varchar', 'nvarchar','char', 'nchar')
Then #InsertTableRowName + ''''''''' + '
When #TempFilterType IN('datetime', 'date')
Then #InsertTableRowName + ''''''''' + Convert(varchar(Max), '
Else
#InsertTableRowName + 'Convert(varchar(Max), '
End
--Determines the Name of the Column
Select #InsertTableRowName = #InsertTableRowName +
Case
When #TempFilterType IN('varchar', 'nvarchar','char', 'nchar')
Then 'ISNULL(' + 'Replace(' + Column_Name + ','''''''','''''''''''')' + ','''')'
When #TempFilterType IN('datetime', 'date')
Then 'ISNULL(' + 'Replace(' + Column_Name + ','''''''','''''''''''')' + ',''12/31/9999'')'
Else
'ISNULL(' + 'Replace(' + Column_Name + ','''''''','''''''''''')' + ',0)'
End
From (
Select Column_Name,
ROW_NUMBER() OVER (Order By Ordinal_Position) As RowNum
From INFORMATION_SCHEMA.COLUMNS
Where Table_Name = #TableName
) As TheRow
Where RowNum = #index
--Finishes Closes each column insert (in every instance)
Set #InsertTableRowName = Case
When #TempFilterType IN('varchar', 'nvarchar','char', 'nchar')
Then #InsertTableRowName + ' + '''''''''
When #TempFilterType IN('datetime', 'date')
Then #InsertTableRowName + ') + '''''''''
Else
#InsertTableRowName + ') '
End
--Links each Row together with commas and plus signs until the very end.
If #index < #rowcount
Begin
Set #InsertTableRowName = Case
When #TempFilterType IN('varchar', 'nvarchar','char', 'nchar')
Then #InsertTableRowName + ' + ' + ''',''' + ' + '
When #TempFilterType IN('datetime', 'date')
Then #InsertTableRowName + ' + '','' + '
Else
#InsertTableRowName + ' + '','' + '
End
End
Set #index = #index + 1
End
--Puts the Query together (without any of the Parameters yet).
--First, determine if a new table should be used instead.
If #NewTableName = ''
Begin
Set #NewTableName = #TableName
End
--Next, Build the Query, and do it accordingly with if there is a Find/Replace asked for.
Set #execFunction = 'Select '
If #VarCharFind <> ''
Begin
Set #execFunction = #execFunction + 'Replace('
End
Set #execFunction = #execFunction + '''insert into ' + #NewTableName + ' Values('' + ' + #InsertTableRowName + ' + '')'' '
If #VarCharFind <> ''
Begin
Set #execFunction = #execFunction + ', ''' + #VarCharFind + ''', ''' + #VarCharReplace + ''') '
End
Set #execFunction = #execFunction + 'From ' + #TableName
--Adds in the optional Parameters
If #OptionalParam <> ''
Begin
Set #execFunction = #execFunction + ' ' + #OptionalParam
End
Set #execFunction = #execFunction + CHAR(13)+CHAR(10)
--Executes the function and pulls an entire set of queries to copy into the new Database
Print #execFunction
Exec(#execFunction)
GO