XML columns compare in SQL Server - sql

I have got 3 columns:
[OldContent] [xml] NULL
[NewContent] [xml] NULL
[OldContent] [xml] NULL
I want to compare the data in two columns. I want to write the results into the third column ([OldContent])
How can I do it in SQL Server?
[OldContent] [xml] NULL, in
Value
<row GUEST_ID="13" GUEST_NAME="VEDAT" GUEST_SURNAME="PALA" ADRESS="IZMIR" />
[NewContent] [xml] NULL, in value
<row GUEST_ID="13" GUEST_NAME="VEDAT35" GUEST_SURNAME="PALA" ADRESS="IZMIR" CITY="DR" CITY_CODE="35" />
I want to write the value in it.
[UpdateContent] [xml] NULL
<row GUEST_NAME="VEDAT35 CITY="DR" CITY_CODE="35" />
I need a procedure to compare XML column values.

It is quite easy to get the data out of XML. Then you may compare your data "as ever". The result you can write out into a new XML with "FOR XML".
Try it like this:
DECLARE #myXML XML=
'<rows>
<row GUEST_ID="13" GUEST_NAME="VEDAT35" GUEST_SURNAME="PALA" ADRESS="IZMIR" CITY="DR" CITY_CODE="35" />
<row GUEST_ID="14" GUEST_NAME="TestGuestName" GUEST_SURNAME="TestSurname" ADRESS="TestAddr" CITY="TestCity" CITY_CODE="11" />
</rows>';
--This is how you retrieve the data
SELECT x.y.value('#GUEST_ID','int')
,x.y.value('#GUEST_NAME','varchar(max)')
,x.y.value('#GUEST_SURNAME','varchar(max)')
,x.y.value('#ADRESS','varchar(max)')
,x.y.value('#CITY','varchar(max)')
,x.y.value('#CITY_CODE','int')
FROM #myXML.nodes('/rows/row') AS x(y)
--This is how you create a new XML with your data
SELECT 13 AS [#GUEST_ID]
,'NewName' AS [#GUEST_NAME]
,'NewSurname' AS [#GUEST_SURNAME]
,'NewAddr' AS [#GUEST_ADRESS]
,'NewCity' AS [#CITY]
,12 AS [#CITY_CODE]
FOR XML PATH('row'),ROOT('rows')

samples table
USE [DENEME]
GO
/****** Object: Table [dbo].[GUESTS] Script Date: 17.07.2015 22:19:35 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[GUESTS](
[GUEST_ID] [int] IDENTITY(1,1) NOT NULL,
[GUEST_NAME] [varchar](50) NULL,
[GUEST_SURNAME] [varchar](50) NULL,
[ADRESS] [varchar](100) NULL,
[CITY] [varchar](50) NULL,
[CITY_CODE] [varchar](10) NULL,
[COUNTRY] [varchar](50) NULL,
[STATUS] [varchar](20) NULL,
[COMMENT] [nvarchar](max) NULL,
PRIMARY KEY CLUSTERED
(
[GUEST_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
SET ANSI_PADDING OFF
GO
USE [DENEME]
GO
/****** Object: Trigger [dbo].[iudt_AutoAuditChanges] Script Date: 17.07.2015 22:20:11 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[iudt_AutoAuditChanges]
ON [dbo].[GUESTS]
AFTER INSERT,DELETE,UPDATE
AS
BEGIN
SET NOCOUNT ON;
declare #AuditType char(1) /* BEN EKELEDM*/
Declare #v_AuditID bigint
/******************************/
if exists (select * from inserted)
if exists (select * from deleted)
SET #AuditType = 'U'
else
SET #AuditType = 'I'
else
SET #AuditType = 'D'
/******************************/
IF OBJECT_ID('dbo.AutoAudit','U') IS NULL BEGIN
CREATE TABLE [dbo].[AutoAudit]
( [AuditID] bigint identity,
[AuditType] Char(1),
[AuditDate] DateTime,
[AuditUserName] varchar(128),
[TableName] varchar(128) NULL,
[OldContent] XML NULL,
[NewContent] XML NULL,
[Updatedcontent] XML NULL
)
ALTER TABLE dbo.AutoAudit ADD CONSTRAINT
PK_AutoAudit PRIMARY KEY CLUSTERED
(
[AuditID]
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [idx_AutoAudit_TableName_AuditDate] ON [dbo]. [AutoAudit]
( [TableName] ASC,
[AuditDate] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
END
Select * Into #AuditDeleted from deleted
Select * Into #AuditInserted from inserted
While (Select COUNT(*) from #AuditDeleted) > 0 OR (Select COUNT(*) from #AuditInserted) > 0
Begin
INSERT INTO [dbo].[AutoAudit]
( [AuditDate],[AuditType], [AuditUserName], [TableName], [OldContent], [NewContent])
SELECT
GETDATE(),
#AuditType,
SUSER_NAME(),
[TableName]=object_name([parent_obj]),
[OldContent]=CAST((SELECT TOP 1 * FROM #AuditDeleted D FOR XML RAW) AS xml),
[NewContent]=CAST((SELECT TOP 1 * FROM #AuditInserted I FOR XML RAW) AS xml)
FROM sysobjects
WHERE
[xtype] = 'tr'
and [name] = OBJECT_NAME(##PROCID)
Set #v_AuditID = SCOPE_IDENTITY()
Delete from AutoAudit
Where AuditID = #v_AuditID
AND Convert(varchar(max),oldContent) = Convert(varchar(max),NewContent)
Delete top(1) from #AuditDeleted
Delete top(1) from #AuditInserted
End
END
I am writing log program.
OldContent:
<row GUEST_ID="19" GUEST_NAME="VEDAT" GUEST_SURNAME="PALA" ADRESS="TURKEY" CITY="TOKAT" CITY_CODE="60" />
newcontent:
<row GUEST_ID="19" GUEST_NAME="VEDAT60" GUEST_SURNAME="PALA" ADRESS="TURKEY" CITY="TOKAT" CITY_CODE="60" STATUS="other" COMMENT="uptaded fields" />
Expected results:
UptadedContent:
<row GUEST_NAME="VEDAT60" STATUS="other" COMMENT="uptaded fields" />
I want compare procedure..
Look this picture
IMG]http://i59.tinypic.com/24nfibl.png[/IMG]

Related

Pivot while changing data types (dynamically)

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)

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?

Violation of UNIQUE KEY constraint during SQL update

I have a simple database table (SQL Server 2008 R2 Express), which has a definition as follows:
ID INT Auto Inc, PK
Name VARCHAR(64) Unique Key
Telephone VARCHAR(128)
I have a stored procedure which I execute to update records within the table which basically does the following:
UPDATE customers
SET Name = #name, Telephone = #Telephone
WHERE id = #id
Currently, I have two entries in the table
ID Name Telephone
1 Fred 01234 567890
2 John 09876 543210
When I call my stored procedure to update the telephone number for John, the SQL that is effectively executed is
UPDATE customers
SET Name = 'John', Telephone = '02468 135790'
WHERE id = 2
This generates a UNIQUE KEY violation on the Name field. Now as the Name field doesn't actually change, why does this occur?
As all database actions are being handled by my app using stored procedures, I could fix this by removing the constraint, and modifying the stored procedures to manually enforce the constraint, but this just seems wrong.
Given that my table actually has many more fields, there must be a generic work around that I can employ to prevent these false constraint problems, without having to generate numerous stored procedures to update specific fields?
Edit: The above table was simplified to keep the question more manageable, I'm pretty sure I've not missed anything important, but for info, the actual definition of the table is as follows
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[companies](
[id] [int] IDENTITY(1,1) NOT NULL,
[typeId] [int] NOT NULL,
[name] [varchar](64) NOT NULL,
[displayName] [varchar](128) NOT NULL,
[deliveryAddress] [varchar](1024) NOT NULL,
[invoiceAddress] [varchar](1024) NOT NULL,
[telephone] [varchar](64) NOT NULL,
[fax] [varchar](64) NOT NULL,
[email] [varchar](256) NOT NULL,
[website] [varchar](256) NULL,
[isActive] [bit] NOT NULL,
CONSTRAINT [PK_companies] 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],
CONSTRAINT [Unique Display Name] UNIQUE NONCLUSTERED
(
[displayName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [Unique Name] UNIQUE NONCLUSTERED
(
[name] 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].[companies] WITH CHECK ADD CONSTRAINT [Company Type] FOREIGN KEY([id])
REFERENCES [dbo].[companyTypes] ([id])
GO
ALTER TABLE [dbo].[companies] CHECK CONSTRAINT [Company Type]
GO
...and the stored procedure
ALTER PROCEDURE UpdateCompany
#id INT,
#typeId INT,
#name VARCHAR(64),
#displayName VARCHAR(128),
#deliveryAddress VARCHAR(1024),
#invoiceAddress VARCHAR(1024),
#telephone VARCHAR(64),
#fax VARCHAR(64),
#email VARCHAR(256),
#website VARCHAR(256),
#isActive BIT
AS
BEGIN
UPDATE companies
SET typeid = #typeid,
name = #name,
displayname = #displayname,
deliveryAddress = #deliveryAddress,
invoiceAddress = #invoiceAddress,
telephone = #telephone,
fax = #fax,
email = #email,
website = #website,
isActive = #isActive
EXEC GetCompany #id
END
GO
You're missing the WHERE in your UPDATE statement so currently it will try and update all rows in the table with the same values.

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