General Trigger that updates a Master/Detail table - sql-server

I've been tasked with creating a generic Trigger(one that will work on all tabled in my database) that will will fire on Insert, Delete, and Update to capture changes done on a table.
I have 2 new tables a Master Table...
CREATE TABLE [dbo].[DATA_HIL_Master](
[MasterId] [int] IDENTITY(1,1) NOT NULL,
[ReferenceTable] [nvarchar](100) NULL,
[ReferenceId] [int] NULL,
[OperationType] [smallint] NULL,
[Last_UserId_Log] [int] NULL,
[Last_WorkstationId_Log] [int] NULL,
[Last_DateTime_Log] [datetime] NULL, PRIMARY KEY CLUSTERED (
[MasterId] 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
And then a Detail table...
CREATE TABLE [dbo].[DATA_HIL_Detail](
[DetailId] [int] IDENTITY(1,1) NOT NULL,
[MasterId] [int] NOT NULL,
[ColumnName] [nvarchar](100) NULL,
[OriginalValue] [nvarchar](max) NULL,
[ModifiedValue] [nvarchar](max) NULL,
PRIMARY KEY CLUSTERED (
[DetailId] 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
My trigger needs to be able to update these tables with the correct information for that update and than table. For Instance I have another table..
CREATE TABLE [dbo].[CNF_Tax2Package](
[Tax2PackageId] [int] IDENTITY(1,1) NOT NULL,
[TaxPackageId] [int] NOT NULL,
[TaxId] [int] NOT NULL,
[Last_UserId_Log] [int] NULL,
[Last_WorkstationId_Log] [int] NULL,
[Last_DateTime_Log] [datetime] NULL,
PRIMARY KEY CLUSTERED
(
[Tax2PackageId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY =
OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED
(
[Tax2PackageId] 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
EveryTime a record is change in this CNF_Tax2Package table I need to up the History tables with information
I do the following UPdate statement
Update CNF_Tax2Package
set TaxPackageid = 1,
Last_UserID_Log = 1098,
Last_WorkstationID_Log = 77,
Last_DateTime_Log = Getdate()
where Tax2PackageID = 2]
I would insert into the DATA_HIL_Master a row with the following information
[MasterId] = (NEWMasterID) [ReferenceTable] = 'CNF_Tax2Package' [ReferenceId] = 2 ---This is the primary Key of the
---table updated. [OperationType] = 'Update' [Last_UserId_Log] = 1098 [Last_WorkstationId_Log] = 77 [Last_DateTime_Log] getdate()
I would then insert into the DATA_HIL_Detail the following rows.
[DetailId] = (NEWID) [MasterId] = (NEWMasterID) (From above) [ColumnName] = 'TaxPackageid' [OriginalValue] = '19' [ModifiedValue] = '1'
[DetailId] = (NEWID) [MasterId] = (NEWMasterID) (From above) [ColumnName] = 'Last_UserID_Log' [OriginalValue] = '1954' [ModifiedValue] = '1098'
[DetailId] = (NEWID) [MasterId] = (NEWMasterID) (From above) [ColumnName] = 'Last_WorkstationId_Log' [OriginalValue] = '55' [ModifiedValue] = '77'
[DetailId] = (NEWID) [MasterId] = (NEWMasterID) (From above) [ColumnName] = 'Last_DateTime_Log' [OriginalValue] = '2018-08-18 [ModifiedValue] = getdate()
Understanding that the trigger must be generic enough to handle all tables in my database with different columns, different primary Keys

Related

INSERT in SQL where foreign key is auto-generated in another table [duplicate]

This question already has answers here:
How to insert a row into another table using last inserted ID?
(4 answers)
Closed 4 months ago.
I have a table 1 with an auto-generated primary key in SQL Server. I have a second table 2 where the auto-generated value from table 1 is a foreign key in table 2.
How can I write a query where I can INSERT into table 2, including the auto-generated value from table 1.
Preferably this would also work in a stored procedure.
Generate scripts:
CREATE TABLE [dbo].[POSTADRESSE](
[AdresseID] [int] IDENTITY(1,1) NOT NULL,
[GateNavn] [varchar](50) NULL,
[GateNR] [varchar](10) NULL,
[PostNR] [int] NULL,
[PostSted] [varchar](30) NULL,
CONSTRAINT [XPKPOSTADRESSE] PRIMARY KEY CLUSTERED
(
[AdresseID] 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
CREATE TABLE [dbo].[KUNDE](
[TelefonNR] [varchar](15) NOT NULL,
[AdresseID] [int] NOT NULL,
[Epost] [varchar](320) NULL,
[Fornavn] [varchar](100) NULL,
[Etternavn] [varchar](100) NULL,
[Passord] [varchar](69) NULL,
CONSTRAINT [XPKKUNDE] PRIMARY KEY CLUSTERED
(
[TelefonNR] ASC,
[AdresseID] 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
This is what I've tried:
INSERT INTO POSTADRESSE(GateNavn, GateNR, PostNR, PostSted)
VALUES ('Storgt', 3, 3901, 'Porsgrunn')
INSERT INTO KUNDE(TelefonNR, AdresseID, Epost, Fornavn, Etternavn, Passord)
VALUES (
47843329,
(SELECT POSTADRESSE.AdresseID FROM POSTADRESSE WHERE POSTADRESSE.GateNavn = 'Storgt'),
'hej#hotmail.se',
'Anton',
'Johanson',
'123abc'
);
Hi #VaBraAnton see this answer will help.
Declare #Identity as int
INSERT INTO POSTADRESSE(GateNavn, GateNR, PostNR, PostSted)
VALUES ('Storgt', 3, 3901, 'Porsgrunn')
Select #Identity=SCOPE_IDENTITY();
INSERT INTO KUNDE(TelefonNR, AdresseID, Epost, Fornavn, Etternavn, Passord)
VALUES (
47843329,
#Identity,
'hej#hotmail.se',
'Anton',
'Johanson',
'123abc'
);
see screen shot

How do I add system versioning to this table definition with clause?

I have the below table definition and I want to add system versioning to it but I can't seem to get it into the WITH clause without SQL Server complaining.
CREATE TABLE [dbo].[Employee](
[EmployeeId] [int] IDENTITY(1,1) NOT NULL,
[FirstName] [varchar](50) NULL,
[LastName] [varchar](50) NULL,
[SysStartTime] [datetime2](7) NOT NULL,
[SysEndTime] [datetime2](7) NOT NULL,
CONSTRAINT [PK_Employee_1] 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]
Here's the system versioning WITH clause.
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE=[dbo].[EmployeeHistory], DATA_CONSISTENCY_CHECK=ON));
It's probably easiest and most succinct to create your table and then add the required system versioning elements:
create table [dbo].[Employee](
[EmployeeId] [int] identity(1,1) not null,
[FirstName] [varchar](50) null,
[LastName] [varchar](50) null
constraint [PK_Employee_1] 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]
alter table dbo.Employee add
SysStartTime datetime2 generated always as row start constraint DF_EmployeeSysStart default SysUtcDateTime(),
SysEndTime datetime2 generated always as row end constraint DF_EmployeeSysEnd default Convert(datetime2, '9999-12-31 23:59:59.9999999'),
period for system_time (SysStartTime,SysEndTime);
alter table Employee set (system_versioning = on (history_table = dbo.EmployeeHistory, data_consistency_check=on));
Edit
To combine in a single create table
create table [dbo].[Employee](
[EmployeeId] [int] identity(1,1) not null,
[FirstName] [varchar](50) null,
[LastName] [varchar](50) null,
[SysStartTime] datetime2 generated always as row start constraint DF_EmployeeSysStart default SysUtcDateTime(),
[SysEndTime] datetime2 generated always as row end hidden constraint DF_EmployeeSysEnd default Convert(datetime2, '9999-12-31 23:59:59.9999999'),
period for system_time (SysStartTime,SysEndTime),
constraint [PK_Employee_1] primary key clustered ( [EmployeeId] asc) with (pad_index = off, statistics_norecompute = off, ignore_dup_key = off, allow_row_locks = on, allow_page_locks = on)
) with ( system_versioning = on (history_table = dbo.EmployeeHistory, data_consistency_check=on))

SQL Select with Join Bringing Odd Result

I know this kind of problem can happen but I have no idea on figuring it out (also, it is in Portuguese, so I will try my best to illustrate my question in English, translating the database structure, fields, etc).
These are the 4 tables that I need for this query:
- Agenda_Cliente (this is the Client table);
- Agenda_Imposto (this is the Taxes table - description for each tax ID);
- Agenda_ClienteImposto (NxN table - relates each Client to the taxes he or she pays);
- Agenda_LogAgenda (that's the core of the query: it contains which tax (by ID: CodigoImposto) was sent to a specific client (by ID as well: CodigoCliente), when the tax was sent (DataHoraEnvio) and when it was accessed (DataHoraAcesso).
The strctures are the following:
CREATE TABLE [dbo].[Agenda_Cliente](
[CodigoCliente] [bigint] IDENTITY(1,1) NOT NULL,
[CodigoEscritorio] [int] NOT NULL,
[RazaoSocial] [varchar](60) NOT NULL,
[NomeFantasia] [varchar](60) NOT NULL,
[Email] [varchar](60) NOT NULL,
[TelefoneComercial] [bigint] NOT NULL,
[TelefoneCelular1] [bigint] NOT NULL,
[TelefoneCelular2] [bigint] NOT NULL,
[CnpjCpf] [bigint] NOT NULL,
[Cep] [int] NOT NULL,
[Endereco] [varchar](80) NOT NULL,
[Bairro] [varchar](60) NOT NULL,
[Municipio] [varchar](60) NOT NULL,
[Estado] [char](2) NOT NULL,
[RegimeTributacao] [int] NOT NULL,
[FlagAtivo] [bit] NOT NULL,
PRIMARY KEY CLUSTERED
(
[CodigoCliente] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Agenda_Imposto](
[CodigoImposto] [int] IDENTITY(1,1) NOT NULL,
[DescricaoImposto] [varchar](30) NOT NULL,
[TipoImposto] [int] NOT NULL,
[DeptoResponsavel] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[CodigoImposto] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Agenda_ClienteImposto](
[CodigoClienteImposto] [bigint] IDENTITY(1,1) NOT NULL,
[CodigoCliente] [bigint] NOT NULL,
[CodigoImposto] [int] NOT NULL,
[DataLimite] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[CodigoClienteImposto] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Also, the FOREIGN KEYS are all OK and working.
So, the problem is: I have the following SQL SELECT query:
SELECT c.CnpjCpf, c.NomeFantasia, i.DescricaoImposto, ci.DataLimite, la.DataHoraEnvio, la.DataHoraAcesso
FROM Agenda_Cliente c
JOIN Agenda_ClienteImposto ci ON ci.CodigoCliente = c.CodigoCliente
JOIN Agenda_Imposto i ON i.CodigoImposto = ci.CodigoImposto
LEFT JOIN Agenda_LogAgenda la ON la.CodigoImposto = i.CodigoImposto
WHERE c.CodigoEscritorio = 1
ORDER BY c.NomeFantasia ASC, ci.DataLimite ASC
It's bringing me this:
But I need it to bring me this:
And if I SELECT * at the Calendar log (Agenda_LogAgenda), there's only one record.
It seems to me that it's something to do with Agenda_ClienteImposto, as far as I tried here, but it may be something about the JOIN clause that I'm not getting, because it's applying the result for "Empresa 1" in "Empresa 3", but "Empresa 3" does not exist in Agenda_LogAgenda.
Any help is appreciated.
Thanks!
The left join to Agenda_LogAgenda is only on CodingoImposto. From the values in the query, 'CRF' probably does exist. Add NomFantasia to the ON clause of the left join.

T-SQL what kind of constraint to use

I have the following two tables (only relevant key columns shown)
CREATE TABLE [dbo].[Jobs](
[ID] [int] IDENTITY(1,1) NOT NULL,
[JobNo] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Jobs] 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]
CREATE TABLE [dbo].[Items](
[JobID] [int] NOT NULL,
[BarcodeNo] [nvarchar](50) NOT NULL,
[SerialNo] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Items_1] PRIMARY KEY CLUSTERED
(
[JobID] ASC,
[BarcodeNo] ASC,
[SerialNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
I need to make sure that when an item is entered, the JobID matches an ID in the Jobs table. It seems, I can't use a FK because the PK in the items table is a composite key of 3 columns.
TIA
Mark
What kind of constraint can I use for this?
A foreign key works fine.
There's no problem with having the single column [dbo].[Items].[JobID] reference the PK of jobs.
CREATE TABLE [dbo].[Jobs]
(
[ID] [INT] IDENTITY(1, 1) NOT NULL,
[JobNo] [NVARCHAR](50) NOT NULL,
CONSTRAINT [PK_Jobs] 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]
CREATE TABLE [dbo].[Items]
(
[JobID] [INT] NOT NULL REFERENCES [dbo].[Jobs]([ID]), /*<-- FK declaration*/
[BarcodeNo] [NVARCHAR](50) NOT NULL,
[SerialNo] [NVARCHAR](50) NOT NULL,
CONSTRAINT [PK_Items_1] PRIMARY KEY CLUSTERED ( [JobID] ASC, [BarcodeNo] ASC, [SerialNo] ASC )
WITH (PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
)
ON [PRIMARY]

Create a stored procedure to populate a table from other (multiple) table columns

I need to create a stored procedure transaction that will pull data from two tables and create a random integer to populate a third table (dbo.patient_address).
I want the following, but I am having a hard time understanding how to script this as a stored procedure.
dbo.address AddressID = dbo.patient_address AddressID,
dbo.patient PatientID = dbo.patient_address PatientID,
RAND is an integer between 1-3 (see dbo.addresstype) = dbo.patient_address AddressTypeID
Below are create statements of all of these tables.
ADDRESS TABLE - 30000 rows in place (complete data set)
CREATE TABLE [dbo].[ADDRESS](
[AddressID] [int] NOT NULL,
[StreetAddress] [varchar](50) NULL,
[City] [varchar](50) NULL,
[State] [varchar](50) NULL,
[PostalCode] [varchar](50) NULL,
CONSTRAINT [ADDRESS_PK] PRIMARY KEY CLUSTERED
(
[AddressID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
PATIENT TABLE - 30000 rows in place (complete data set)
CREATE TABLE [dbo].[PATIENT](
[PatientID] [int] NOT NULL,
[PatientFName] [varchar](50) NOT NULL,
[PatientLName] [varchar](50) NOT NULL,
[GenderID] [int] NOT NULL,
[DateOfBirth] [date] NOT NULL,
CONSTRAINT [PATIENT_PK] PRIMARY KEY CLUSTERED
(
[PatientID] 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
ADDRESS TYPE - 3 choices (home, billing, work) – integer between 1 - 3
CREATE TABLE [dbo].[ADDRESS_TYPE](
[AddressTypeID] [int] NOT NULL,
[AddressTypeName] [varchar](10) NOT NULL,
[AddressTypeDescr] [varchar](10) NULL,
CONSTRAINT [ADDRESS_TYPE_PK] PRIMARY KEY CLUSTERED
(
[AddressTypeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO [dbo].[ADDRESS_TYPE]
([AddressTypeID],[AddressTypeName],[AddressTypeDescr])
Values ('1','Home','Home'), ('2','Bill','Billing'), ('3','Work','Work')
This is the final table that I want to populate from all of the above tables using a stored procedure transaction.
CREATE TABLE [dbo].[PATIENT_ADDRESS](
[PatientID] [int] NOT NULL,
[AddressID] [int] NOT NULL,
[AddressTypeID] [int] NULL,
CONSTRAINT [PATIENT_ADDRESS_PK] PRIMARY KEY CLUSTERED
(
[PatientID] ASC,
[AddressID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Try this:
INSERT INTO PATIENT_ADDRESS
SELECT PatientID, AddressID,
CONVERT(INT,(ABS(CHECKSUM(NEWID())/2148000000.))*3)+1 AS AddressTypeID
FROM (
SELECT PatientID, ROW_NUMBER() OVER (ORDER BY PatientID) AS RowNum
FROM dbo.PATIENT
) x
INNER JOIN (
SELECT AddressID, ROW_NUMBER() OVER (ORDER BY AddressID) AS RowNum
FROM dbo.ADDRESS
) y ON x.RowNum = y.RowNum

Resources