I am puzzled with a query.
I need find out the LAST row added in a table with a column with datatype Uniqueidentifier
column is:
aspnet_Applications.ApplicationId
Notes: This column Uniqueidentifier it is NOT and IDENTITY Column.
I need also take the last row inserted and update it on a different table
aspnet_Users.ApplicationId
I tried to use SCOPE_IDENTITY in MS SQL 2008 but does not work because SCOPE_IDENTITY is working only with IDENTITY column.
Here my code. Any ideas?
CREATE DATABASE Test;
GO
USE Test;
GO
-- Create entities
CREATE TABLE [dbo].[aspnet_Applications](
[ApplicationName] [nvarchar](256) NOT NULL,
[LoweredApplicationName] [nvarchar](256) NOT NULL,
[ApplicationId] [uniqueidentifier] NOT NULL,
[Description] [nvarchar](256) NULL,
PRIMARY KEY NONCLUSTERED
(
[ApplicationId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED
(
[LoweredApplicationName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED
(
[ApplicationName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[aspnet_Applications] ADD DEFAULT (newid()) FOR [ApplicationId]
GO
CREATE TABLE [dbo].[aspnet_Users](
[ApplicationId] [uniqueidentifier] NOT NULL,
[UserId] [uniqueidentifier] NOT NULL,
[UserName] [nvarchar](256) NOT NULL,
[LoweredUserName] [nvarchar](256) NOT NULL,
[MobileAlias] [nvarchar](16) NULL,
[IsAnonymous] [bit] NOT NULL,
[LastActivityDate] [datetime] NOT NULL,
PRIMARY KEY NONCLUSTERED
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[aspnet_Users] WITH CHECK ADD FOREIGN KEY([ApplicationId])
REFERENCES [dbo].[aspnet_Applications] ([ApplicationId])
GO
ALTER TABLE [dbo].[aspnet_Users] ADD DEFAULT (newid()) FOR [UserId]
GO
ALTER TABLE [dbo].[aspnet_Users] ADD DEFAULT (NULL) FOR [MobileAlias]
GO
ALTER TABLE [dbo].[aspnet_Users] ADD DEFAULT ((0)) FOR [IsAnonymous]
GO
-- Add data
DECLARE #MyIdentity binary(16);
INSERT INTO dbo.aspnet_Applications
(
ApplicationName,
LoweredApplicationName,
Description
)
VALUES
(
'x',
'x',
'Dummy text'
);
SET #MyIdentity = SCOPE_IDENTITY(); -- DOES NOT WORK
PRINT #MyIdentity; -- DOES NOT WORK
INSERT INTO dbo.aspnet_Users
(
ApplicationId,
UserName,
LoweredUserName,
MobileAlias,
IsAnonymous,
LastActivityDate
)
VALUES
(
#MyIdentity,
'Administrator',
'administrator',
'',
0,
sysutcdatetime()
);
It's a little more work, but for your inserts, even though you already have a DEFAULT value on the ApplicationID, you could do this:
DECLARE #MyIdentity uniqueidentifier;
SET #MyIdentity = NewID();
INSERT INTO dbo.aspnet_Applications
(
ApplicationName,
LoweredApplicationName,
ApplicationId,
Description
)
VALUES
(
'x',
'x',
#MyIdentity,
'Dummy text'
);
SELECT #MyIdentity
Essentially, you set the GUID beforehand, so you already know what you will be inserting.
You could use the OUTPUT clause to get the inserted value(s) back but LBT's answer is probably more straightforward and efficient.
DECLARE #ids table(id uniqueidentifier)
INSERT INTO dbo.aspnet_Applications
(
ApplicationName,
LoweredApplicationName,
Description
)
OUTPUT INSERTED.ApplicationId into #ids
VALUES
(
'x',
'x',
'Dummy text'
)
By the way if it wasn't for the Foreign Key you could use composable DML for this as below.
INSERT
INTO dbo.aspnet_Users
(
ApplicationId ,
UserName ,
LoweredUserName,
MobileAlias ,
IsAnonymous ,
LastActivityDate
)
SELECT ApplicationId ,
'Administrator',
'administrator',
'' ,
0 ,
sysutcdatetime()
FROM ( INSERT
INTO dbo.aspnet_Applications
(
ApplicationName ,
LoweredApplicationName,
Description
)
OUTPUT INSERTED.ApplicationId VALUES
(
'x',
'x',
'Dummy text'
)
) AS I
Related
I am having a little trouble with my after insert trigger it does not update/insert into the table and I am not sure why.
I have the tables employee, position, certification, employeecertification, positioncertification.
What I need to do is after a Position is assigned a Certification then all employees that are defined in that position (Employee:PositionId = Ins.PositionId] need to get the certification added (if it does not already exist in their record) , I might need to update them where they do exist (but for the moment do not believe that will be a requirement).
I have been getting a couple different results (neither is correct)
1: EmployeeId can not insert null into EmployeeId
2: On some other test data - nothing is inserted.
I have the following trigger with the sql for creation of tables that follows:
The Trigger
CREATE TRIGGER [dbo].[trig_InsNew_PositionCertification]
ON [dbo].[PositionCertification]
AFTER INSERT
AS
Insert into EmployeeCertification
(CertificationId, EmployeeId)
Select Ins.CertificationId, Emp.EmployeeId
From inserted Ins
Left Join dbo.Employee Emp On Emp.PositionId = Ins.PositionId
Left Join dbo.Certification Trw On Trw.CertificationId = Ins.CertificationId
WHERE NOT EXISTS
(SELECT EmployeeId, CertificationId
FROM
EmployeeCertification
WHERE EmployeeId = Emp.EmployeeId AND CertificationId = Ins.CertificationId);
GO
ALTER TABLE [dbo].[PositionCertification] ENABLE TRIGGER [trig_InsNew_PositionCertification]
GO
CREATE TABLES:
CREATE TABLE [dbo].[Position](
[PositionId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Position] PRIMARY KEY CLUSTERED
(
[PositionId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[Employee](
[EmployeeId] [int] IDENTITY(1,1) NOT NULL,
[EmployeeName] [nvarchar](512) NOT NULL,
[PositionId] [int] NOT NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED
(
[EmployeeId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Employee] WITH CHECK ADD CONSTRAINT [FK_Employee_Position] FOREIGN KEY([PositionId])
REFERENCES [dbo].[Position] ([PositionId])
GO
ALTER TABLE [dbo].[Position] CHECK CONSTRAINT [FK_Employee_Position]
GO
CREATE TABLE [dbo].[Certification](
[CertificationId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](512) NOT NULL,
CONSTRAINT [PK_Certification] PRIMARY KEY CLUSTERED
(
[CertificationId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[EmployeeCertification](
[EmployeeCertificationId] [int] IDENTITY(1,1) NOT NULL,
[EmployeeId] [int] NOT NULL,
[CertificationId] [int] NOT NULL,
CONSTRAINT [PK_EmployeeCertification] PRIMARY KEY CLUSTERED
(
[EmployeeId] ASC,
[CertificationId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[EmployeeCertification] WITH CHECK ADD CONSTRAINT [FK_EmpCertification_Certification] FOREIGN KEY([CertificationId])
REFERENCES [dbo].[Certification] ([CertificationId])
GO
ALTER TABLE [dbo].[EmployeeCertification] CHECK CONSTRAINT [FK_EmpCertification_Certification]
GO
ALTER TABLE [dbo].[EmployeeCertification] WITH CHECK ADD CONSTRAINT [FK_EmpCertification_Employee] FOREIGN KEY([EmployeeId])
REFERENCES [dbo].[Employee] ([EmployeeId])
GO
ALTER TABLE [dbo].[EmployeeCertification] CHECK CONSTRAINT [FK_EmpCertification_Employee]
GO
CREATE TABLE [dbo].[PositionCertification](
[PositionCertificationId] [int] IDENTITY(1,1) NOT NULL,
[PositionId] [int] NOT NULL,
[CertificationId] [int] NOT NULL,
CONSTRAINT [PK_PositionCertification] PRIMARY KEY CLUSTERED
(
[PositionId] ASC,
[CertificationId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
Let's say I have 3 tables: users, customattributes, and customattributevalues. End user can add custom attributes by selecting a name and type for the attribute, and the edit the values for any user.
Here are my users:
id
firstname
lastname
active
datecreated
username
email
3
Ellen
Ripley
1
3/25/2235
78439
Rip8439#Weyland-Yutani.com
5
Johnny
Rico
1
4/16/2675
Roughneck31
RicoJ31#Roughnecks.com
customattributes (can be added to anytime)
id
fullname
uniquename
type
1
Hire Date
hiredate
date
2
Employee ID
eeid
int
3
Supervisor
supervisor
nvarchar(50)
4
Assigned Ship
assignedship
nvarchar(50)
5
Job Title
jobtitle
nvarchar(50)
type I currently have as sysname datatype.
customattributevalues (can be edited anytime)
id
attributeid
userid
value
1
1
3
2335-03-25
2
2
3
78439
3
3
3
Burke, Carter
4
4
3
Sulaco
5
5
3
Consultant
6
1
5
2675-04-16
7
2
5
78440
8
3
5
LT Rasczak
9
4
5
Rodger Young
10
5
5
Private
value I currently have as sql_variant datatype
So here is my question: how can I create a report that shows all employees and their attributes, 1 line per employee, without knowing how many custom attributes there are --and-- crucially, I want to explicitly convert each column to the correct data type
Desired output:
firstname
lastname
datecreated
username
email
Hire Date
Employee ID
Supervisor
Assigned Ship
Job Title
Ellen
Ripley
2235-03-25
78439
Rip8439#Weyland-Yutani.com
2335-03-25
78439
Burke, Carter
Sulaco
Consultant
Johnnie
Rico
2675-04-16
Roughneck31
RicoJ31#Roughnecks.com
2675-04-16
78440
LT Rasczak
Rodger Young
Private
I've already learned to do the dynamic column headers using dynamic queries, but it is the type conversion that is escaping me.
I'm adapting this solution for custom fields, but the limitation to this solution is you have to know each custom field to make the type conversion.
Here is what I've tried. I got the correct output, except for the type conversions.
Query:
DECLARE #columns NVARCHAR(MAX) = '';
DECLARE #sqlcmd NVARCHAR(MAX) = '';
SELECT #columns += QUOTENAME(fullname) + ','
FROM customattributesx ca
ORDER BY ca.id;
SET #columns = LEFT(#columns, LEN(#columns) - 1);
--PRINT #columns;
SET #sqlcmd = '
SELECT * FROM (
SELECT userid
,firstname
,lastname
,datecreated
,username
,email
,fullname
,value
FROM (
SELECT u.id as userid
,u.firstname
,u.lastname
,u.datecreated
,u.username
,u.email
,ca.id
,ca.fullname as fullname
,ca.uniquename
,ca.type
,cav.value as value
FROM dbo.users u
CROSS JOIN customattributesx ca
INNER JOIN customattributevaluesx cav
ON cav.attributeid = ca.id AND cav.userid = u.id
--ORDER BY u.id asc, ca.id asc
) t1
) t2
PIVOT (
MIN(value)
FOR fullname IN ('+#columns+')
) as pivottable
';
--print #sqlcmd
EXECUTE (#sqlcmd)
Create Tables:
USE [CTMS]
GO
/****** Object: Table [dbo].[users] Script Date: 11/24/2021 9:29:16 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[users](
[id] [int] IDENTITY(1,1) NOT NULL,
[firstname] [nvarchar](max) NULL,
[lastname] [nvarchar](max) NULL,
[active] [bit] NOT NULL,
[datecreated] [datetime2](7) NOT NULL,
[username] [nvarchar](256) NULL,
[email] [nvarchar](256) NULL,
[emailconfirmed] [bit] NOT NULL,
[passwordhash] [nvarchar](max) NULL,
[twofactorenabled] [bit] NOT NULL,
[lockoutend] [datetimeoffset](7) NULL,
[eockoutenabled] [bit] NOT NULL,
[accessfailedcount] [int] NOT NULL,
[qrcode] [nvarchar](50) NULL,
CONSTRAINT [PK_id] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk_email] UNIQUE NONCLUSTERED
(
[email] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk_qrcode] UNIQUE NONCLUSTERED
(
[qrcode] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk_username] UNIQUE NONCLUSTERED
(
[username] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[users] ADD DEFAULT (getutcdate()) FOR [datecreated]
GO
USE [CTMS]
GO
/****** Object: Table [dbo].[customattributesx] Script Date: 11/24/2021 9:31:09 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[customattributesx](
[id] [smallint] IDENTITY(1,1) NOT NULL,
[fullname] [nvarchar](50) NOT NULL,
[uniquename] [nvarchar](50) NOT NULL,
[type] [sysname] NOT NULL,
CONSTRAINT [PK_customattributesx] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk1_customattributesx] UNIQUE NONCLUSTERED
(
[uniquename] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
USE [CTMS]
GO
/****** Object: Table [dbo].[customattributevaluesx] Script Date: 11/24/2021 9:31:27 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[customattributevaluesx](
[id] [int] IDENTITY(1,1) NOT NULL,
[attributeid] [smallint] NOT NULL,
[userid] [int] NOT NULL,
[value] [sql_variant] NOT NULL,
CONSTRAINT [PK_customattributevaluesx] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk1_customattributevaluesx] UNIQUE NONCLUSTERED
(
[attributeid] ASC,
[userid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[customattributevaluesx] WITH CHECK ADD CONSTRAINT [fk1_customattributesvaluesx] FOREIGN KEY([attributeid])
REFERENCES [dbo].[customattributesx] ([id])
GO
ALTER TABLE [dbo].[customattributevaluesx] CHECK CONSTRAINT [fk1_customattributesvaluesx]
GO
ALTER TABLE [dbo].[customattributevaluesx] WITH CHECK ADD CONSTRAINT [fk2_customattributesvaluesx] FOREIGN KEY([userid])
REFERENCES [dbo].[users] ([id])
GO
ALTER TABLE [dbo].[customattributevaluesx] CHECK CONSTRAINT [fk2_customattributesvaluesx]
GO
If you must convert the datatype (could really be a presentation layer thing), then a dynamic conditional aggregation should do the trick.
Example
Declare #SQL nvarchar(max) ='
Select U.*' +
(
Select concat(',',quotename(fullname),'=max(case when attributeid=',id,' then try_convert(',type,',value) end)')
From customattributes
For XML Path ('')
)+'
From users U
Join customattributesvalues V on U.ID=V.userid
Group By U.ID
,U.FirstName
,U.LastName
,U.active
,U.datecreated
,U.username
,U.email
'
--print #SQL
Exec(#SQL)
Results
The Generated SQL Looks Like This
Select U.*
,[Hire Date]=max(case when attributeid=1 then try_convert(date,value) end)
,[Employee ID]=max(case when attributeid=2 then try_convert(int,value) end)
,[Supervisor]=max(case when attributeid=3 then try_convert(nvarchar(50),value) end)
,[Assigned Ship]=max(case when attributeid=4 then try_convert(nvarchar(50),value) end)
,[Job Title]=max(case when attributeid=5 then try_convert(nvarchar(50),value) end)
From #users U
Join #customattributesvalues V on U.ID=V.userid
Group By U.ID
,U.FirstName
,U.LastName
,U.active
,U.datecreated
,U.username
,U.email
SQL_VARIANT can be cast to a destination data type.
Modify part of the dynamic query where you generate column list, to generate two lists. One list is for PIVOT part and the other for SELECT part where you cast you data types.
Example is based on the article you refer to in your question:
DECLARE #PivotList NVARCHAR( MAX )
DECLARE #SelectList NVARCHAR( MAX )
SELECT #SelectList = NULL, #PivotList = NULL
-- Column list with CAST e.g. CAST( eeid AS INT ) AS eeid
-- Data types come from your customattributes table
SELECT #SelectList = COALESCE( #SelectList + ',','') + 'CAST( ' + uniquename + ' AS [type] ) AS ' + uniquename,
-- Just a column list that goes into PIVOT operator
#PivotList = COALESCE( #PivotList + ',','') + uniquename
-- Your tables for attribute values and attribute type definitions
FROM customattributes AS ca
DECLARE #SQLQuery NVARCHAR(MAX)
SET #SQLQuery =
'SELECT StudID , '+#SelectList+'
FROM
( SELECT SM.StudID, S.SubjectName, SM.Score
FROM StudentMarks SM
INNER JOIN Subjects S
ON Sm.SubjectID = S.SubjectID
) AS tbl
PIVOT
( Sum(Score)
FOR SubjectName IN ('+#PivotList+') ) as pvt'
EXEC(#SQLQuery)
We have a trigger that we are trying to update so that when a record is updated, the trigger will update a second table. When we activate the change, we get an error
Violation of PRIMARY KEY contstraint 'KPRIMARY_SO_SalesOrderHeader". Cannot insert duplicate key in object 'dbo.SO_SalesOrderHeader". The duplicate key is XXXXXX.
I'm really confused by this because I don't see in the trigger where we are trying to insert a key.
ALTER Trigger [dbo].[SO_SALESORDERHEADER_onOrderChange]
ON [dbo].[SO_SalesOrderHeader]
FOR INSERT, UPDATE
AS
SET NOCOUNT ON;
--+
INSERT INTO dbo.OrderUpdateQueue (SourceId, OrderNumber, Action)
SELECT DISTINCT
N'SO', Inserted.SALESORDERNO, N'U'
FROM
Inserted
LEFT JOIN
dbo.OrderUpdateQueue ON (Inserted.SALESORDERNO = OrderUpdateQueue.OrderNumber)
AND (OrderUpdateQueue.SourceID = N'SO')
AND (OrderUpdateQueue.Action = N'U')
WHERE
(OrderUpdateQueue.[Key] IS NULL)
AND (Inserted.SALESORDERNO IS NOT NULL);
--+ New Trigger Stuff
UPDATE MO
SET MO.[ShipDate] = I.ShipExpireDate
FROM [BACKEND_db].[dbo].[Order] MO
INNER JOIN Inserted I ON I.SalesOrderNo = MO.OrderId
WHERE MO.ShipDate <> I.ShipExpireDate;
CREATE TABLE [dbo].[SO_SalesOrderHeader](
[SalesOrderNo] [varchar](7) NOT NULL
CONSTRAINT [KPRIMARY_SO_SalesOrderHeader] PRIMARY KEY CLUSTERED
(
[SalesOrderNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[OrderUpdateQueue](
[Key] [int] IDENTITY(1,1) NOT NULL,
[SourceId] [nvarchar](50) NOT NULL,
[OrderNumber] [nvarchar](50) NOT NULL,
[Action] [nchar](1) NOT NULL,
CONSTRAINT [PK_OrderUpdateQueue] PRIMARY KEY CLUSTERED
(
[Key] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
USE [BACKEND_db]
CREATE TABLE [dbo].[Order](
[Key] [int] IDENTITY(1,1) NOT NULL,
[OrderId] [nvarchar](10) NULL,
[ShipDate] [datetime] NULL
CONSTRAINT [PK_MasOrder] PRIMARY KEY CLUSTERED
(
[Key] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
GO
How you do not post the schema of OrderUpdateQueue table, I believe the pk is the OrderNumber field. You can try to change your trigger to:
ALTER Trigger [dbo].[SO_SALESORDERHEADER_onOrderChange]
ON [dbo].[SO_SalesOrderHeader]
FOR INSERT, UPDATE
AS
SET NOCOUNT ON;
--+
INSERT INTO dbo.OrderUpdateQueue (SourceId, OrderNumber, Action)
SELECT DISTINCT
N'SO', Inserted.SALESORDERNO, N'U'
FROM
Inserted
WHERE not exists (SELECT 1 FROM dbo.OrderUpdateQueue where Inserted.SALESORDERNO = OrderUpdateQueue.OrderNumber)
UPDATE MO
SET MO.[ShipDate] = I.ShipExpireDate
FROM [BACKEND_db].[dbo].[Order] MO
INNER JOIN Inserted I ON I.SalesOrderNo = MO.OrderId
WHERE MO.ShipDate <> I.ShipExpireDate;
I have a table UserInfoComputed whose data comes from UserInfo and UserInfoComputed also have foreign key constraint to UserCompany.
I have a trigger on UserInfo which inserts/updates/deletes rows into UserInfoComputed
Here is my UserInfoComputed table:
CREATE TABLE [dbo].[UserInfoComputed ](
[id] AS (CONVERT([bigint],replace([law_id],'LAW',''),(0))) PERSISTED NOT NULL,
[company_id] [varchar](12) NOT NULL,
[first_name] [varchar](30) NOT NULL,
[last_name] [varchar](30) NOT NULL,
[law_id] [varchar](12) NOT NULL,
[type] [smallint] NULL,
[dtype] AS (case [TYPE] when (1) then 'Corporate' else 'Non-Corporate' end) PERSISTED NOT NULL,
CONSTRAINT [PK_UserInfoComputed] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[UserInfoComputed] WITH CHECK ADD CONSTRAINT [FK668581C04AA07B12] FOREIGN KEY([company_id])
REFERENCES [dbo].[UserCompany] ([id])
GO
Here is my UserInfo table
CREATE TABLE [dbo].[UserInfo](
[ID] [varchar](12) NOT NULL,
[CompanyID] [varchar](12) NULL,
[Status] [char](4) NULL,
[FirstName] [varchar](30) NOT NULL,
[LastName] [varchar](30) NOT NULL,
CONSTRAINT [PK_UserInfo] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
Here is the UserCompany table
CREATE TABLE [dbo].[UserCompany](
[ID] [varchar](12) NOT NULL,
[Name] [varchar](100) NULL,
[ShortName] [varchar](25) NULL,
[Type] [smallint] NULL,
CONSTRAINT [PK_UserCompany] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
The type values are either 1 or 2 or 3
Here is my trigger on UserInfo table
CREATE TRIGGER [dbo].[ReconcileUserInfoComputed]
ON [dbo].[UserInformation]
AFTER INSERT,DELETE,UPDATE
AS
IF ##ROWCOUNT = 0 -- exit trigger when zero records affected
BEGIN
RETURN
END
IF EXISTS (SELECT * FROM INSERTED)
BEGIN
IF EXISTS (SELECT * FROM DELETED)
BEGIN
--UPDATE
UPDATE [dbo].[UserInformationComputed]
SET -- use new values from inserted
first_name = (SELECT FirstName FROM inserted),
last_name = (SELECT LastName FROM inserted),
law_id = (SELECT ID FROM inserted)
WHERE law_id = (SELECT ID FROM deleted)
END
ELSE
BEGIN
--INSERT
INSERT INTO [dbo].[UserInfoComputed] (first_name,last_name, law_id)
SELECT FirstName, LastName, ID FROM inserted
END
END
ELSE IF EXISTS(SELECT * FROM DELETED)
BEGIN
--DELETE
DELETE FROM [dbo].[UserInfoComputed]
WHERE law_id = (SELECT id FROM deleted)
END
GO
Is there a way to insert or update type value from UserCompany into UserInfoComputed table in ReconcileUserInfoComputed trigger?
I wish to migrate some data from a single table into these new THREE tables.
Here's my destination schema:
Notice that I need to insert into the first Location table .. grab the SCOPE_IDENTITY() .. then insert the rows into the Boundary and Country tables.
The SCOPE_IDENTITY() is killing me :( meaning, I can only see a way to do this via CURSORS. Is there a better alternative?
UPDATE
Here's the scripts for the DB Schema....
Location
CREATE TABLE [dbo].[Locations](
[LocationId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
[OriginalLocationId] [int] NOT NULL,
CONSTRAINT [PK_Locations] PRIMARY KEY CLUSTERED
(
[LocationId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
)
Country
CREATE TABLE [dbo].[Locations_Country](
[IsoCode] [nchar](2) NOT NULL,
[LocationId] [int] NOT NULL,
CONSTRAINT [PK_Locations_Country] PRIMARY KEY CLUSTERED
(
[LocationId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Locations_Country] WITH CHECK ADD CONSTRAINT [FK_Country_inherits_Location] FOREIGN KEY([LocationId])
REFERENCES [dbo].[Locations] ([LocationId])
GO
ALTER TABLE [dbo].[Locations_Country] CHECK CONSTRAINT [FK_Country_inherits_Location]
GO
Boundary
CREATE TABLE [dbo].[Boundaries](
[LocationId] [int] NOT NULL,
[CentrePoint] [varbinary](max) NOT NULL,
[OriginalBoundary] [varbinary](max) NULL,
[LargeReducedBoundary] [varbinary](max) NULL,
[MediumReducedBoundary] [varbinary](max) NULL,
[SmallReducedBoundary] [varbinary](max) NULL,
CONSTRAINT [PK_Boundaries] PRIMARY KEY CLUSTERED
(
[LocationId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Boundaries] WITH CHECK ADD CONSTRAINT [FK_LocationBoundary] FOREIGN KEY([LocationId])
REFERENCES [dbo].[Locations] ([LocationId])
GO
ALTER TABLE [dbo].[Boundaries] CHECK CONSTRAINT [FK_LocationBoundary]
GO
I don't see a need for SCOPE_IDENTITY or cursors if you approach the data in order of the parent/child relationship:
INSERT INTO LOCATION
SELECT t.name,
t.originallocationid
FROM ORIGINAL_TABLE t
GROUP BY t.name, t.originallocationid
INSERT INTO COUNTRY
SELECT DISTINCT
t.isocode,
l.locationid
FROM ORIGINAL_TABLE t
JOIN LOCATION l ON l.name = t.name
AND l.originallocationid = t.originalocationid
INSERT INTO BOUNDARY
SELECT DISTINCT
l.locationid,
t.centrepoint,
t.originalboundary,
t.largereducedboundary,
t.mediumreducedboundary,
t.smallreducedboundary
FROM ORIGINAL_TABLE t
JOIN LOCATION l ON l.name = t.name
AND l.originallocationid = t.originalocationid
After loading your Location table you could create a query that joins Location with your source single table. The join criteria would be the natural key (is that the Name column?) and it would return the new LocationId along with the Boundary data. The results would inserted into the new Boundary table.