Update Statement Incorrectly Applying - sql-server

I am trying to update 45000 rows with missing values on SQL Server 2000 sp4 Database.
I will try to simulate the table setup and conditions of values below:
I have two tables. One is holding valid transactions and the other has missing values in certain rows.
--Table #Trans holds valid transactions
Create Table #trans (
[DocumentNumber] [char](21) NOT NULL,
[CustomerName] [char](21) NOT NULL,
[CustomerID] [char](31) NOT NULL,
[ACTINDX] [int] NOT NULL,
[CRDTAMNT] [numeric](19, 5) NOT NULL,
[DEBITAMT] [numeric](19, 5) NOT NULL,
[TRXSORCE] [char](30) NOT NULL,
[TRXDATE] [datetime] NOT NULL
)
INSERT INTO #trans ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[TRXSORCE],[TRXDATE])
Values('INV20123','Andrew Sesinyi','A0001',2501,25620.00,0.000,'SALESTRN15012015','15-Jan-2015')
INSERT INTO #trans ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[TRXSORCE],[TRXDATE])
Values('INV20123','Andrew Sesinyi','A0001',2201,0.000,25620.00,'SALESTRN15012015','15-Jan-2015')
INSERT INTO #trans ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[TRXSORCE],[TRXDATE])
Values('PMTRN00155','Bame Moonwa','B0001',1700,1550.00,0.0000,'PYMNTTRN17012015','17-Jan-2015')
INSERT INTO #trans ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[TRXSORCE],[TRXDATE])
Values('PMTRN00155','Bame Moonwa','B0001',1900,0.0000,1550.00,'PYMNTTRN17012015','17-Jan-2015')
INSERT INTO #trans ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[TRXSORCE],[TRXDATE])
Values('PMTRN00156','OLERATO PHAMA','OL0001',1900,0.0000,1020.00,'PYMNTTRN17012015','17-Jan-2015')
INSERT INTO #trans ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[TRXSORCE],[TRXDATE])
Values('PMTRN00156','OLERATO PHAMA','OL0001',1700,1020.00,0.0000,'PYMNTTRN17012015','17-Jan-2015')
INSERT INTO #trans ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[TRXSORCE],[TRXDATE])
Values('INV20124','Bame Moonwa','B0001',2501,18000.00,0.000,'SALESTRN15012015','15-Jan-2015')
INSERT INTO #trans ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[TRXSORCE],[TRXDATE])
Values('INV20124','Bame Moonwa','B0001',2201,0.000,18000.00,'SALESTRN15012015','15-Jan-2015')
--Tables #GL holds some of the transactions with missing values i.e --DocumentNumber,CustomerID A and CustomerName
Create Table #GL(
[DocumentNumber] [char](21) ,
[CustomerName] [char](21),
[CustomerID] [char](31),
[ACTINDX] [int] NOT NULL,
[CRDTAMNT] [numeric](19, 5) NOT NULL,
[DEBITAMT] [numeric](19, 5) NOT NULL,
[ORTRXSORCE] [char](30) NOT NULL,
[TRXDATE] [datetime] NOT NULL
)
INSERT INTO #GL ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[ORTRXSORCE],[TRXDATE])
Values('','Andrew Sesinyi','A0001',2501,25620.00,0.000,'SALESTRN15012015','15-Jan-2015')
INSERT INTO #GL ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[ORTRXSORCE],[TRXDATE])
Values('','Andrew Sesinyi','A0001',2201,0.000,25620.00,'SALESTRN15012015','15-Jan-2015')
INSERT INTO #GL ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[ORTRXSORCE],[TRXDATE])
Values('','Bame Moonwa','B0001',1700,1550.00,0.0000,'PYMNTTRN17012015','17-Jan-2015')
INSERT INTO #GL ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[ORTRXSORCE],[TRXDATE])
Values('','Bame Moonwa','B0001',1900,0.0000,1550.00,'PYMNTTRN17012015','17-Jan-2015')
INSERT INTO #GL ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[ORTRXSORCE],[TRXDATE])
Values('','','',1900,0.0000,1020.00,'PYMNTTRN17012015','17-Jan-2015')
INSERT INTO #GL ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[ORTRXSORCE],[TRXDATE])
Values('','','',1700,1020.00,0.0000,'PYMNTTRN17012015','17-Jan-2015')
INSERT INTO #GL ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[ORTRXSORCE],[TRXDATE])
Values('INV20124','','',2501,18000.00,0.000,'SALESTRN15012015','15-Jan-2015')
INSERT INTO #GL ([DocumentNumber],[CustomerName],[CustomerID],[ACTINDX],[CRDTAMNT],[DEBITAMT],[ORTRXSORCE],[TRXDATE])
Values('INV20124','','',2201,0.000,18000.00,'SALESTRN15012015','15-Jan-2015')
When I run the following update statement incorrect updates are rendered to the #GL Records. Is there an alternative method or better way to apply an update records in this scenario.
UPDATE #GL
SET DocumentNumber = TR.DocumentNumber
, CustomerName = TR.CustomerName
,CustomerID =TR.CustomerID
FROM #GL GL
INNER JOIN #trans TR ON GL.ORTRXSORCE = TR.TRXSORCE
WHERE GL.ACTINDX = TR.ACTINDX
AND GL.DEBITAMT = TR.DEBITAMT
OR GL.CRDTAMNT = TR.CRDTAMNT
AND GL.TRXDATE = TR.TRXDATE
N.B I am trying to use this method to update 45000 records that have missing values.
N.B Multiple transactions can be posted as a batch to the #GL hence the shared TRXSORCE
Many Thanks for your insight in advance.

I bet you mean
WHERE GL.ACTINDX = TR.ACTINDX
AND (GL.DEBITAMT = TR.DEBITAMT OR GL.CRDTAMNT = TR.CRDTAMNT)
AND GL.TRXDATE = TR.TRXDATE

Related

After insert trigger doesn't work when using Inserted

I'm trying to write a trigger on my Employees table that should not allow the insertion of a new employee that has a hire date that is older than the hire date of his boss
CREATE TABLE [dbo].[Employees]
(
[EID] [int] IDENTITY(1,1) NOT NULL,
[Ename] [nvarchar](20) NOT NULL,
[Gender] [nvarchar](1) NOT NULL,
[IsMarried] [nvarchar](1) NOT NULL,
[Birthdate] [date] NOT NULL,
[HireDate] [date] NOT NULL,
[Salary] [float] NOT NULL,
[Notes] [nvarchar](200) NULL,
[NationalityID] [int] NULL,
[BossID] [int] NULL,
CONSTRAINT [PK_Employees]
PRIMARY KEY CLUSTERED ()
)
And here's the trigger code:
CREATE TRIGGER [dbo].[Trig_04]
ON [dbo].[Employees]
AFTER INSERT
AS
BEGIN
IF ((SELECT INSERTED.HireDate FROM INSERTED WHERE BossID <> EID) <
(SELECT Employees.HireDate FROM Employees
WHERE EID IN (SELECT Employees.BossID FROM Employees WHERE BossID <> EID)))
ROLLBACK
END
It executes normally (no errors) but it just doesn't work, but when I was using the employees table in the subquery instead of the inserted table, it was working normally. Does anyone have an answer for this?
You have to write triggers in SQL Server to handle the fact that INSERTED could contain multiple records. You cannot assume it will only be a single record. I think the following is what you are looking for:
if exists (
select 1
from Inserted I
where I.BossID <> I.EID
and I.HireDate < (select E.HireDate from Employees E where E.EID = I.BossID)
) begin
ROLLBACK;
end

After Trigger for Update and Insert failing

I am writing a trigger for keeping audit record for one table for Insert and Update records.
CREATE TABLE [dbo].[AppLog](
[TableName] [varchar](32) NOT NULL,
[ColumnName] [varchar](32) NOT NULL,
[RecordId] [varchar](20) NOT NULL,
[OldValue] [varchar](2000) NULL,
[NewValue] [varchar](2000) NULL,
[UpdatedBy] [varchar](200) NULL,
[UpdatedOn] [datetime] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Persons](
[Personid] [int] IDENTITY(1,1) NOT NULL,
[LastName] [varchar](255) NOT NULL,
[FirstName] [varchar](255) NULL,
[Age] [int] NULL
) ON [PRIMARY]
GO
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT
AS
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,UpdatedBy ,UpdatedOn )
SELECT 'Persons', 'LastName', COALESCE(i.Personid,NULL),
d.LastName, i.LastName, CURRENT_USER, GETDATE()
FROM Persons pv
LEFT JOIN INSERTED i ON pv.Personid = i.Personid
LEFT JOIN DELETED d ON pv.Personid = d.Personid;
GO
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('Satish','Parida',40);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('SKP','Tada',90);
The last insert is failing as it is trying to insert null to recordid column in applog table, could someone explain or fix the issue.
The statement that is failing is the one below:
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('SKP','Tada',90);
This is because in your Trigger you are using Persons are your "base" table and the performing a LEFT JOIN to both inserted and deleted. As result when you try to perform the above INSERT, values from the previous INSERT are used as well in the trigger's dataset. The person 'Parida' doesn't appear in the table inserted for your second INSERT, and so COALESCE(i.Personid,NULL) returns NULL; as I mentioned in my comment, there' no point using COALESCE to return NULL, as if an expression's value evaluates to NULL it will return NULL. As RecordID (which is what COALESCE(i.Personid,NULL) is being inserted into) can't have the value NULL the INSERT fails and the whole transaction is rolled back.
I suspect that what you want for your trigger is the below:
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT
AS BEGIN
INSERT INTO AppLog (TableName,
ColumnName,
RecordId,
OldValue,
NewValue,
UpdatedBy,
UpdatedOn)
SELECT 'Persons',
'LastName',
i.Personid,
d.LastName,
i.LastName,
CURRENT_USER,
GETDATE()
FROM inserted AS i
LEFT JOIN deleted AS d ON i.Personid = d.Personid;
END;
inserted will always have at least 1 row for an UPDATE or an INSERT. inserted would not for a DELETE, but your trigger won't fire on that DML event so using inserted as the "base" table seems the correct choice.
Following code should work
CREATE TABLE [dbo].[AppLog](
[TableName] [varchar](32) NOT NULL,
[ColumnName] [varchar](32) NOT NULL,
[RecordId] [varchar](20) NOT NULL,
[OldValue] [varchar](2000) NULL,
[NewValue] [varchar](2000) NULL,
[UpdatedBy] [varchar](200) NULL,
[UpdatedOn] [datetime] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Persons](
[Personid] [int] IDENTITY(1,1) NOT NULL,
[LastName] [varchar](255) NOT NULL,
[FirstName] [varchar](255) NULL,
[Age] [int] NULL
) ON [PRIMARY]
GO
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT
AS
if exists(SELECT * from inserted) and exists (SELECT * from deleted)
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,UpdatedBy ,UpdatedOn )
SELECT 'Persons', 'LastName', COALESCE(i.Personid,NULL),
d.LastName, i.LastName, CURRENT_USER, GETDATE()
FROM Persons pv
INNER JOIN INSERTED i ON pv.Personid = i.Personid
INNER JOIN DELETED d ON pv.Personid = d.Personid;
END
If exists (Select * from inserted) and not exists(Select * from deleted)
begin
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,UpdatedBy ,UpdatedOn )
SELECT
'Persons', 'LastName',i.Personid,NULL,i.LastName,CURRENT_USER,GETDATE()
FROM
inserted AS i
END
GO
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('Satish','Parida',40);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('SKP','Tada',90);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('abc','def',90);
INSERT INTO Persons (FirstName,LastName,age)
VALUES ('gg','hh',90);
UPDATE dbo.Persons SET LastName='Paridachanged' WHERE Personid=1
SELECT * FROM Persons
SELECT * FROM AppLog
USE KnockKnockDev;
GO
IF OBJECT_ID('dbo.AuditRecord', 'TR') IS NOT NULL
DROP TRIGGER dbo.AuditRecord;
GO
CREATE TRIGGER AuditRecord ON dbo.Persons
AFTER UPDATE, INSERT, DELETE
AS
DECLARE #Action as char(1)
DECLARE #Count as int
DECLARE #TableName as char(32)
DECLARE #ColumnName as char (32)
SET #TableName = 'Persons'
SET #ColumnName = 'LastName'
SET #Action = 'I' -- Set Action to 'I'nsert by default.
SELECT #Count = COUNT(*) FROM DELETED
IF #Count > 0
BEGIN
SELECT #Count = COUNT(*) FROM INSERTED
IF #Count > 0
SET #Action = 'U' -- Set Action to 'U'pdated.
ELSE
SET #Action = 'D' -- Set Action to 'D'eleted.
END
IF #Action = 'I'
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,Action ,UpdatedBy ,UpdatedOn )
SELECT #TableName, #ColumnName, Personid,
NULL, LastName, #Action, CURRENT_USER, GETDATE()
FROM INSERTED;
END
ELSE IF #Action = 'D'
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,Action ,UpdatedBy ,UpdatedOn )
SELECT #TableName, #ColumnName, Personid,
LastName, NULL, #Action, CURRENT_USER, GETDATE()
FROM DELETED;
END
ELSE
BEGIN
INSERT INTO AppLog
(TableName ,ColumnName ,RecordId ,OldValue ,NewValue ,Action ,UpdatedBy ,UpdatedOn )
SELECT #TableName, #ColumnName, i.Personid,
d.LastName, i.LastName, #Action, CURRENT_USER, GETDATE()
FROM Persons pv
INNER JOIN INSERTED i ON pv.Personid = i.Personid
INNER JOIN DELETED d ON pv.Personid = d.Personid;
END
GO

UPDATE doesn't allow to INSERT null in FK field

I have a SQL Server database and in a table there's a lookup column which is a "nullable FK" linked to a master table.
There's a data import process in which we fetch data from table01_staging into table01. This is the UPDATE statement which is failing (if CarrierID is null) -
DECLARE #code as nvarchar(10); SET #code = 'xyz';
UPDATE table01
SET CarrierID = t2.CarrierID
FROM table01 AS t1
INNER JOIN table01_staging AS t2 ON t1.Code = #code;
WHERE t1.Code = #code;
It goes fine if the CarrierID is not null. In fact I can successfully execute:
UPDATE table01
SET CarrierID = null
WHERE t1.Code = 'xyz';
So setting null is not the problem but it doesn't work when its updated from the staging table which has a null value. How can I make it right?
Error : The UPDATE statement conflicted with the FOREIGN KEY constraint FK_table01_MasterCarrier. The conflict occurred in database table01, table dbo.MasterCarrier, column ID.
> EDIT 02: DONE!. Updated the first SQL to show my variable usage - which I believe was the culprit. Correcting the JOIN operation as follows with a COLLATion conversion error fix makes it work -
DECLARE #code as nvarchar(10); SET #code = 'xyz';
UPDATE table01
SET CarrierID = t2.CarrierID
FROM table01 AS t1
INNER JOIN table01_staging AS t2 ON t1.Code = t2.code COLLATE SQL_Latin1_General_CP1_CI_AS
WHERE t1.Code = #code;
Thank you all, esp. Zhang. I deserve a -1 for not being able to understand the JOIN clause properly :-)
Does table01_staging have the same Foreign Key Constraint on CarrierID?
If not, check whether there are some CarrierID not existing in MasterCarrier table.
select * from table01_staging t
where not exists (select 1 from MasterCarrier m where m.ID = t.CarrierID)
!!UPDATE!!
I created the sample table and data. It worked without any issue.
CREATE TABLE [dbo].MasterCarrier(
[id] [int] IDENTITY NOT NULL,
[NAME] [varchar](10) NULL,
CONSTRAINT [PK_mastertable] PRIMARY KEY CLUSTERED
(
[id] ASC
)
)
GO
CREATE TABLE [dbo].[table01](
[id] [int] NOT NULL,
[CarrierID] [int] NULL,
[Code] [varchar](10) NULL
)
GO
ALTER TABLE [dbo].table01 WITH CHECK ADD CONSTRAINT [FK_table01_MasterCarrier] FOREIGN KEY([CarrierID])
REFERENCES [dbo].[MasterCarrier] ([id])
GO
ALTER TABLE [dbo].table01 CHECK CONSTRAINT [FK_table01_MasterCarrier]
GO
CREATE TABLE [dbo].[table01_staging](
[id] [int] NOT NULL,
[CarrierID] [int] NULL,
[Code] [varchar](10) NULL
)
GO
--Insert sample data
INSERT INTO MasterCarrier (NAME) VALUES ('carrier');
INSERT INTO table01 (id, CarrierID, Code) VALUES (1, 1, 'abc'), (2, NULL, 'abc'),(3, 1, 'ddd');
INSERT INTO table01_staging (id, CarrierID, Code) VALUES (1, 1, 'abc'), (2, NULL, 'abc'),(3, 1, 'ddd');
UPDATE table01
SET CarrierID=t2.CarrierID
FROM table01 AS t1
INNER JOIN table01_staging AS t2 ON t1.ID = t2.ID
WHERE t1.Code='abc'
It gets (2 rows affected) message.

TRIGGER AFTER INSERT SELECT MIN(COUNT) insert ID

I'm trying to create a trigger after an insert on the eventss table. The trigger should select the Bcoordinator_ID from the bookingCoordinator table where they have the minimum number of occurrences in the eventss table.
Here's my table data followed by the trigger. It doesn't like the minCount in the values, I think it's looking for and int.
DROP TABLE eventsBooking
CREATE TABLE eventsBooking
(
EBK INT NOT NULL IDENTITY(100, 1),
booking_ID AS 'EBK'+CAST( ebk as varchar(10)) PERSISTED PRIMARY KEY,
bookingDate DATE,
Bcoordinator_ID VARCHAR (20),
eventss_ID VARCHAR (20) NOT NULL
)
INSERT INTO eventsBooking
VALUES ('2015-01-07 11:23:00', NULL, 'EVT100');
Eventss table:
EVT INT NOT NULL IDENTITY(100, 1),
eventss_ID AS 'EVT' + CAST(evt as varchar(10)) PERSISTED PRIMARY KEY,
eventsName varchar(50),
noOfStages SMALLINT,
noOfRounds SMALLINT,
eventsDate DATE,
entryFee DECIMAL (7,2),
venue_ID VARCHAR (20) NOT NULL,
judges_ID VARCHAR (20)
INSERT INTO eventss
VALUES ('Swimming Gala 2015', '3', '7', '2015-01-07 09:00:00', '35.00', 'VEN101', 'JUD100');
CREATE TABLE bookingCoordinator
(
BCO INT NOT NULL IDENTITY(100, 1),
Bcoordinator_ID AS 'BCO'+CAST( bco as varchar(10)) PERSISTED PRIMARY KEY,
forename varchar(20) NOT NULL,
familyName varchar(50)
)
INSERT INTO bookingCoordinator VALUES ('Steve', 'Wills');
Trigger:
CREATE TRIGGER TRGinsertJudge
ON [dbo].[eventss]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.eventsBooking (Bcoordinator_ID, bookingDate, Eventss_ID)
VALUES(minCount, getdate(), 100)
SELECT MIN(COUNT(Bcoordinator_ID)) AS minCount
FROM eventsBooking
END
You can't do an aggregation of an aggregation i.e. MIN(COUNT(1))
If you just want the Bcoordinatior_ID with the least counts in eventsBooking, do this
select top 1 bcoordinator_id
from eventsBooking
group by bcoordinator_id
order by count(1) asc
And you don't use VALUES() in an INSERT INTO ... SELECT statement
Also, in your current code, since eventsBooking.bcoordinator_id is always null, you need to join to the actual table of bookingCoordinators to return booking coordinators without any events booked.
So your complete trigger statement should be
INSERT INTO dbo.eventsBooking (Bcoordinator_ID, bookingDate, Eventss_ID)
select
top 1
bookingcoordinator.bcoordinator_id, getdate(), 100
from bookingCoordinator left join eventsBooking
on bookingCoordinator.Bcoordinator_ID = eventsBooking.Bcoordinator_ID
group by bookingcoordinator.bcoordinator_id
order by count(1) asc

Persisted computed column with subquery

I have something like this
create function Answers_Index(#id int, #questionID int)
returns int
as begin
return (select count([ID]) from [Answers] where [ID] < #id and [ID_Question] = #questionID)
end
go
create table Answers
(
[ID] int not null identity(1, 1),
[ID_Question] int not null,
[Text] nvarchar(100) not null,
[Index] as [dbo].[Answers_Index]([ID], [ID_Question]),
)
go
insert into Answers ([ID_Question], [Text]) values
(1, '1: first'),
(2, '2: first'),
(1, '1: second'),
(2, '2: second'),
(2, '2: third')
select * from [Answers]
Which works great, however it tends to slow down queries quite a bit. How can I make column Index persisted? I have tried following:
create table Answers
(
[ID] int not null identity(1, 1),
[ID_Question] int not null,
[Text] nvarchar(100) not null,
)
go
create function Answers_Index(#id int, #questionID int)
returns int
with schemabinding
as begin
return (select count([ID]) from [dbo].[Answers] where [ID] < #id and [ID_Question] = #questionID)
end
go
alter table Answers add [Index] as [dbo].[Answers_Index]([ID], [ID_Question]) persisted
go
insert into Answers ([ID_Question], [Text]) values
(1, '1: first'),
(2, '2: first'),
(1, '1: second'),
(2, '2: second'),
(2, '2: third')
select * from [Answers]
But that throws following error: Computed column 'Index' in table 'Answers' cannot be persisted because the column does user or system data access. Or should I just forget about it and use [Index] int not null default(0) and fill it in on insert trigger?
edit: thank you, final solution:
create trigger [TRG_Answers_Insert]
on [Answers]
for insert, update
as
update [Answers] set [Index] = (select count([ID]) from [Answers] where [ID] < a.[ID] and [ID_Question] = a.[ID_Question])
from [Answers] a
inner join [inserted] i on a.ID = i.ID
go
You could change the column to be a normal column and then update its value when you INSERT/UPDATE that row using a trigger.
create table Answers
(
[ID] int not null identity(1, 1),
[ID_Question] int not null,
[Text] nvarchar(100) not null,
[Index] Int null
)
CREATE TRIGGER trgAnswersIU
ON Answers
FOR INSERT,UPDATE
AS
DECLARE #id int
DECLARE #questionID int
SELECT #id = inserted.ID, #questionID = inserted.ID_question
UPDATE Answer a
SET Index = (select count([ID]) from [Answers] where [ID] < #id and [ID_Question] = #questionID)
WHERE a.ID = #id AND a.ID_question = #questionID
GO
NB* This is not fully correct as it wont work correctly on UPDATE as we wont have the "inserted" table to reference to get the ID and questionid. There is a way around this but i cant remember it right now :(
Checkout this for more info
Computed columns only store the formula of the calculation to perform. That is why it will be slower when querying the computed column from the table. If you want to persist the values to an actual table column, then you are correct about using a trigger.

Resources