Pivot while changing data types (dynamically) - sql

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)

Related

SQL Server : dynamic concat not working with case in order by

I have a issue where concat isn't concatenating rows into a single string.
Here is the row data
<B>Case1 Number</B>: 123<BR/>
<B>Contact Email</B>: dfFff<BR/>
<B>Contact Phone Number</B>: <BR/>
<B>Reason for Escalation</B>: fddf<BR/>
<B>Contact Preference</B>: Email<BR/>
This is the query that works
declare #body nvarchar(MAX),
#details nvarchar(MAX)
set #details = ''
select #details = #details + '<B>' + f.name + '</B>: ' + COALESCE( s.select_value, d.field_data) + CHAR(13)+'<BR/>'
from primaryTable d
inner join fields f on f.field_id = d.field_id
left outer join select_fields s on s.field_id = d.field_id
and s.select_text = d.field_data
where data_id = 123
order by f.sort_id
This query doesn't work
declare #body nvarchar(MAX),
#details nvarchar(MAX)
set #details = ''
select #details = #details + '<B>' + f.name + '</B>: ' + COALESCE( s.select_value, d.field_data) + CHAR(13)+'<BR/>'
from primaryTable d
inner join fields f on f.field_id = d.field_id
left outer join select_fields s on s.field_id = d.field_id
and s.select_text = d.field_data
where data_id = 123
order by
case
when f.parent_id = 0
then f.sort_id
else (select fs.sort_id + 1
from fields fs
where fs.field_id = f.parent_id)
end,
case
when f.sort_id = 0 then 1
end desc,
f.sort_id
The above query only returns
<B>Contact Phone Number</B>:
<BR/>
I am using SQL Server 2012
As per request here are the table DDL
CREATE TABLE [dbo].[primaryTable ](
[na_fields_data_id] [int] IDENTITY(1,1) NOT NULL,
[data_id] [int] NOT NULL,
[field_id] [int] NOT NULL,
[field_data] [varchar](max) NULL CONSTRAINT [DF__na_survey__field__1332DBDC] DEFAULT (NULL),
CONSTRAINT [PK__na_surve__5E098220114A936A] PRIMARY KEY CLUSTERED
(
[na_fields_data_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
CREATE TABLE [dbo].[select_fields](
[field_select_id] [int] IDENTITY(1,1) NOT NULL,
[field_id] [int] NOT NULL,
[select_text] [varchar](255) NULL DEFAULT (NULL),
[select_value] [varchar](255) NULL DEFAULT (NULL),
[sort_id] [int] NULL DEFAULT (NULL),
PRIMARY KEY CLUSTERED
(
[field_select_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
CREATE TABLE [dbo].[fields ](
[field_select_id] [int] IDENTITY(1,1) NOT NULL,
[field_id] [int] NOT NULL,
[select_text] [varchar](255) NULL DEFAULT (NULL),
[select_value] [varchar](255) NULL DEFAULT (NULL),
[sort_id] [int] NULL DEFAULT (NULL),
PRIMARY KEY CLUSTERED
(
[field_select_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
Sorry for the late response, i got completely caught up with other stuff.
So the way i solved was this by taking the dynamic sql output and dumping it into a temp table and then using the temp table to contact the final output.
Example:
select '<B>' + f.name + '</B>: ' + COALESCE( s.select_value, d.field_data) + CHAR(13)+'<BR/>' 'SELECTVALUE'
into #TempDump
from primaryTable d
inner join fields f on f.field_id = d.field_id
left outer join select_fields s on s.field_id = d.field_id
and s.select_text = d.field_data
where data_id = 123
order by
case
when f.parent_id = 0
then f.sort_id
else (select fs.sort_id + 1
from fields fs
where fs.field_id = f.parent_id)
end,
case
when f.sort_id = 0 then 1
end desc,
f.sort_id
SELECT #details = #details + x.SELECTVALUE FROM #TempDump x

SQL Server: aggregate error on grouping

I have a table called tasks, which lists different tasks a worker can complete. Then i have a relationship table that links a completed task to a worker.
I'm trying to write query that groups the tasks into a list based on the worker id, but the query gives me the following error (see below).
Column 'mater.dbo.worker_task_completion.FK_task_id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Tables
CREATE TABLE [dbo].[tasks]
(
[task_id] [int] IDENTITY(1,1) NOT NULL,
[name] [nvarchar](50) NOT NULL,
[icon] [nvarchar](max) NULL,
[isActive] [int] NOT NULL,
[time] [int] NOT NULL,
CONSTRAINT [PK_tasks] PRIMARY KEY CLUSTERED
(
[task_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]
CREATE TABLE [dbo].[worker_task_completion]
(
[FK_worker_id] [int] NOT NULL,
[FK_task_id] [int] NOT NULL,
[update_date] [datetime] NOT NULL,
CONSTRAINT [PK_worker_task_completion] PRIMARY KEY CLUSTERED
(
[FK_worker_id] ASC,
[FK_task_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]
Query
SELECT top 100 wtc.FK_worker_id,
tasks = Stuff((SELECT ', ' + dbo.tasks.NAME
FROM dbo.tasks
WHERE dbo.tasks.task_id =
wtc.FK_task_id
FOR xml path ('')), 1, 1, '')
FROM dbo.worker_task_completion AS wtc
LEFT JOIN dbo.tasks AS tc
ON tc.task_id = wtc.fk_task_id
-- WHERE wtc.FK_worker_id IN ()
GROUP BY wtc.FK_worker_id
Hmmm. You cannot use a non-aggregated column for the correlation clause. The solution is to move the JOIN into the subquery:
SELECT top 100 wtc.FK_worker_id,
stuff((SELECT ', ' + t.NAME
FROM dbo.worker_task_completion wtc2 JOIN
dbo.tasks t
ON t.task_id = wtc2.FK_task_id
WHERE wtc2.FK_worker_id = wtc.FK_worker_id
FOR xml path ('')
), 1, 2, ''
) as tasks
FROM (SELECT DISTINCT wtc.FK_worker_id
FROM dbo.worker_task_completion wtc
) wtc
-- WHERE wtc.FK_worker_id IN ()
Note that I changed the second argument for STUFF(). Presumably, you want to remove the space as well as the comma.
;WITH CTE_worker_task_completion
AS (SELECT [FK_worker_id]
,[FK_task_id]
FROM [dbo].[worker_task_completion])
------------------------------------------
SELECT [WT].[FK_worker_id]
,[Task]=Stuff(
(
SELECT ', '+[T].[Name]
FROM [dbo].[tasks] AS [T]
INNER JOIN CTE_worker_task_completion AS [WTC]
ON [T].[Task_ID]=[WTC].[Task_ID]
Where [WT].[Worker_ID]=[WTC].[Worker_ID]
ORDER BY [T].[Name] FOR XML PATH('')
),1,1,'')
FROM CTE_worker_task_completion AS [WT]
GROUP BY [WT].[FK_worker_id];

What is the optimal select according to you?

What is the optimal select according to you?
select #MailTo=ISNULL((select data from filedata where descid=3104 and DataId=evt04) ,'')
from event_21
where evtid=#nFileId
or
select #MailTo=ISNULL(data ,'')
from event_21
innerjoin filedata on event_21.evt04=filedata.dataid
where descid=3104
and evtid=#nFileId
Obviously "join" is faster than "inline select query". I have tested with 1000 rows. You can also test. here is the sample test code.
CREATE TABLE [dbo].[tableA](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
CONSTRAINT [PK_tableA] 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
CREATE TABLE [dbo].[tableB](
[RowId] [int] IDENTITY(1,1) NOT NULL,
[Id] [int] NOT NULL,
[Designation] [nvarchar](100) NULL,
CONSTRAINT [PK_tableB] PRIMARY KEY CLUSTERED
(
[RowId] 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
Declare #Min Int = 1
,#Max Int = 1000
While (#Min <= #Max)
Begin
Insert Into tableA(Name)
Select 'Name would be the name of - ' + Cast(#Min As Nvarchar(10))
Insert Into tableB(Id,Designation)
Select #Min
,'Desig could be the name of - Name' + Cast(#Min As Nvarchar(10))
Select #Min = #Min + 1
End
First look # inline select query
-- inline query
Select a.Id
,a.Name
,(Select Designation From tableB As b Where b.Id = a.Id) As Designation
From tableA As a With (Nolock)
output:
Execution Plan:
now the Join query :-
---- join
Select a.Id
,a.Name
,b.Designation
From tableA As a With (Nolock)
Join tableB As b On a.Id = b.Id
execution plan for join query :-
you can see the clear difference.

SQL Server 2008 Trigger to Update/Insert/Delete From Multiple Tables

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?

Retrieve last row inserted with Uniqueidentifier that it is not IDENTITY

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