Currently have this query:
ALTER PROCEDURE [dbo].[spCreateTaskInstances]
#TaskId INT,
#CreatedByUserId INT,
#DueDates dbo.DateList READONLY
AS
BEGIN
SET NOCOUNT ON
INSERT INTO dbo.taskinstance (TaskId, CreatedById, DueDate, RowGuid, CreatedDate)
VALUES (#TaskId, #CreatedByUserId,
(SELECT CAST(d.item as date) FROM #DueDates d),
NEWID(), GETUTCDATE())
END
Obviously, this fails because when I pass more than one DateTime.
Am I forced to use a for loop here?
Just use that table-valued parameter like table - proper set-based approach, no messy while or for loop needed:
ALTER PROCEDURE [dbo].[spCreateTaskInstances]
#TaskId INT,
#CreatedByUserId INT,
#DueDates dbo.DateList READONLY
AS
BEGIN
SET NOCOUNT ON
INSERT INTO dbo.taskinstance (TaskId, CreatedById, DueDate, RowGuid, CreatedDate)
SELECT
#TaskId, #CreatedByUserId, CAST(d.item AS DATE), NEWID(), GETUTCDATE()
FROM
#DueDates d
END
Related
I have a table called flights with the following attributes: flight_id, date, start_time_actual, end_time_actual, rout_id, plane_id
I need to create and AFTER UPDATE, INSERT trigger to prevent the insertion or modification in the date column of dates before 2016 and after 2019.
I created the following trigger but I am not sure how to state the restriction:
create trigger DateRestriction
on flights
after insert, update
as
set nocount on
BEGIN
IF EXISTS(SELECT* FROM inserted) AND NOT EXISTS(SELECT * FROM deleted)
BEGIN
............
ELSEIF EXISTS (SELECT* FROM inserted) AND EXISTS( SELECT * FROM deleted)
BEGIN
declare #temporalinserted table(
id INT IDENTITY,
flight_id INT,
date date,
start_time_actual time,
end_time_actual time,
route_id INT,
plane_id INT);
declare #temporaldeleted table(
id INT IDENTITY,
flight_id INT,
date date,
start_time_actual time,
end_time_actual time,
route_id INT,
plane_id INT);
INSERT INTO #temporalinserted(flight_id, date, start_time_actual, end_time_actual, route_id,
plane_id)
SELECT flight_id, date, start_time_actual, end_time_actual, route_id, plane_id
FROM inserted
INSERT INTO #temporaldeleted(flight_id, date, start_time_actual, end_time_actual, route_id,
plane_id)
SELECT flight_id, date, start_time_actual, end_time_actual, route_id, plane_id
FROM deleted
..........
the dots should be where the restriction code should go. Is there other way to write this code? or what do I need to add in order to make it work? Any help would be greatly appreciated.
To raise an error in SQL and rollback the transaction (block the insert) you can do something like this:
RAISERROR ('Error Message',
16, -- Severity (16 is typically user-defined)
1); -- State (can be any # 0 - 255)
ROLLBACK TRANSACTION;
RETURN
This is the basic structure of my query. If I insert into a #temp table then the query runs in about two seconds:
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
declare #table table
(
locationKey int,
DateKey date,
totalcount bigint,
locationCount int,
LastDateOnAir date,
Aging int
)
;with cteSum as
(
select
fact.locationid as 'locationKey'
,cast([datetime] as date) as 'datekey'
,sum(totalcount) as 'totalcount'
,count(fact.locationCell) as 'locationCount'
,sum(period) as 'period'
FROM [dbo].[MasterTable] fact inner join Dim dim on
fact.locationid = dim.location
WHERE cast([datetime] as date) >= '2017-09-21'
group by
fact.locationid, cast([datetime] as date)
)
select
locationKey, datekey, totalcount, locationCount into #temp
FROM cteSum
--insert into #table
--(locationKey, datekey, totalcount, locationCount)
--select
--locationKey, datekey, totalcount, locationCount
--FROM cteSum
If I insert into the #table variable, the whole query runs in about eight seconds. The insert to a table variable adds six seconds to the execution.
Are table variables that much slower than temp tables? We're talking about 2,000 rows that are being inserted.
Thanks.
For testing performance:
OPTION(RECOMPILE)
OPTION(MAXDOP 1)
SET STATISTICS TIME ON
Temp table & variable table objects are almost identical...
I have written a stored procedure based on a set of process, I'm just passing a single parameter as input to the procedure but it seems it is not taking the value. But when I give input value instead of parameter in the procedure it is working.
There is no mistake in the flow of process, but seems something missing in the procedure syntax end.
below is the stored procedure I used.
ALTER PROCEDURE [TransferIn]
#ponumber NVARCHAR = NULL
AS
BEGIN
--step 1 Delete Temp Pur_ID
IF EXISTS (
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'Pur_ID_IN')
DROP TABLE Pur_ID_IN;
-- =============================================
--step 2 select PO Number
--IF #ponumber IS NOT NULL
SELECT
ponumber, id
INTO Pur_ID_IN
FROM purchaseorder
WHERE potype IN (2, 4)
AND status = 0
AND ponumber = #ponumber;
-- =============================================
--step 3
--delete Temp. Tabel P_Test20_12_IN
IF EXISTS (
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'P_Test20_12_IN')
DROP TABLE P_Test20_12_IN;
-- =============================================
-- step 4 (Insert Data For Invoice To Temp Tabel After Group )
SELECT
ItemDescription, PurchaseOrderID,
SUM(QuantityOrdered) AS QuantityOrdered,
itemid, Price
INTO P_Test20_12_IN
FROM PurchaseOrderEntry
WHERE PurchaseOrderID IN (SELECT id FROM Pur_ID_IN)
GROUP BY
ItemDescription, StoreID, PurchaseOrderID,
itemid, Price;
--order by 3
-- =============================================
-- step 5 Delete Record From PurchaseOrderEntry
DELETE PurchaseOrderEntry
FROM PurchaseOrderEntry
WHERE PurchaseOrderID IN (SELECT id FROM Pur_ID_IN);
-- =============================================
INSERT INTO [W07].[dbo].[PurchaseOrderEntry] ([ItemDescription], [LastUpdated], [PurchaseOrderID], [QuantityOrdered], [ItemID], [Price])
SELECT
[ItemDescription],
GETDATE() AS [LastUpdated],
[PurchaseOrderID], [QuantityOrdered],
[ItemID], [Price]
FROM
P_Test20_12_IN;
END
Problem is
#ponumber nvarchar = null
change it to
#ponumber nvarchar(max) = null
Note:If you do NOT specify the size(char, nchar, varchar, nvarchar),
sql server will default to 1 character.
ALTER PROCEDURE [TransferIn]
(
#ponumber NVARCHAR(100)
)
AS BEGIN
SET NOCOUNT ON
IF OBJECT_ID('tempdb.dbo.#temp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp (id INT PRIMARY KEY)
INSERT INTO #temp (id)
SELECT /*DISTINCT*/ id
FROM dbo.purchaseorder
WHERE potype IN (2, 4)
AND [status] = 0
AND ponumber = #ponumber
IF OBJECT_ID('tempdb.dbo.#temp2') IS NOT NULL
DROP TABLE #temp2
SELECT ItemDescription,
PurchaseOrderID,
SUM(QuantityOrdered) AS QuantityOrdered,
itemid,
Price
INTO #temp2
FROM PurchaseOrderEntry
WHERE PurchaseOrderID IN (SELECT * FROM #temp)
GROUP BY ItemDescription,
StoreID, --?
PurchaseOrderID,
itemid,
Price;
DELETE PurchaseOrderEntry
FROM PurchaseOrderEntry
WHERE PurchaseOrderID IN (SELECT * FROM #temp)
INSERT INTO [W07].[dbo].[PurchaseOrderEntry] ([ItemDescription], [LastUpdated], [PurchaseOrderID], [QuantityOrdered], [ItemID], [Price])
SELECT [ItemDescription],
GETDATE() AS [LastUpdated],
[PurchaseOrderID],
[QuantityOrdered],
[ItemID],
[Price]
FROM #temp2
END
I have created a trigger for a asset_verification. Whenever a new record is inserted in this table, the same record is inserted in the asset_verification_history table because of this trigger.
The trigger is as follows
Create trigger [dbo].[tr_insert_after_asset_verification] on [dbo].[asset_verification]
for insert
As
Begin
declare #verification_id int
declare #id int
declare #audit_id int
declare #date date
declare #status varchar(15)
declare #remarks varchar(200)
declare #creationDate datetime
declare #modificationDate datetime
declare #updatedBy int
declare #audit_action varchar(20)
Select #verification_id = i.verification_id from inserted i
If #verification_id IS NOT NULL
Begin
Select #id = i.id from inserted i
Select #audit_id = i.audit_id from inserted i
Select #date = i.date from inserted i
Select #status = i.status from inserted i
Select #remarks = i.remarks from inserted i
Select #creationDate = i.creationDate from inserted i
Select #modificationDate = i.modificationDate from inserted i
Select #updatedBy = i.updatedBy from inserted i
set #audit_action = 'Insert Record'
INSERT INTO [dbo].[asset_verification_history]
([verification_id]
,[id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy]
,[audit_action])
VALUES
(#verification_id
,#id
,#audit_id
,#date
,#status
,#remarks
,#creationDate
,#modificationDate
,#updatedBy
,#audit_action)
End
End
When I insert the data in the asset_verification table using a procedure in which OPEN XML is used, then this trigger works only for the first record. For the rest of the records the trigger doesn't work
The procedure is as follows
Create procedure [dbo].[usp_AddVerificationBulkData]
(
#vXML XML
)
As
Begin
DECLARE #DocHandle INT
SET NOCOUNT ON
EXEC sp_xml_preparedocument #DocHandle OUTPUT, #vXML
Update asset_verification
set
audit_id = x.AuditId,
id = x.SerialId,
date = x.VerificationDate,
status = x.Status
,remarks = x.Remarks
,creationDate = x.CreatedOn
,modificationDate = x.ModifiedOn
,updatedBy = x.ModifiedBy
From
asset_verification a
Inner Join
OpenXml(#DocHandle,'/ArrayOfAssetVerificationModel/AssetVerificationModel',2)
With(SerialId int, AuditId int, VerificationDate datetime, Status int, Remarks varchar(200), CreatedOn datetime, ModifiedOn datetime, ModifiedBy int) x
On a.audit_id = x.AuditId where a.id = x.SerialId;
INSERT INTO [dbo].[asset_verification]
([id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy])
select SerialId,AuditId,VerificationDate,Status,Remarks,CreatedOn,ModifiedOn,ModifiedBy from OpenXml(#DocHandle,'/ArrayOfAssetVerificationModel/AssetVerificationModel',2)
With(SerialId int, AuditId int, VerificationDate datetime, Status int, Remarks varchar(200), CreatedOn datetime, ModifiedOn datetime, ModifiedBy int) x
where SerialId NOT IN (select a.id from asset_verification a where a.audit_id = x.AuditId);
End
Problem:- How to make this trigger work for every record that is inserted through Open XML ?
You've made the classic mistake of thinking that triggers fire once-per-row. They dont, it's once-per-action, so the inserted pseudo table holds all the rows affected by the action. Your trigger needs to work in a set based manner, not row based. Try this;
CREATE TRIGGER [dbo].[tr_insert_after_asset_verification] ON [dbo].[asset_verification] FOR INSERT AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[asset_verification_history]
( [verification_id]
,[id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy]
,[audit_action]
)
SELECT i.verification_id
,i.id
,i.audit_id
,i.date
,i.status
,i.remarks
,i.creationDate
,i.modificationDate
,i.updatedBy
,'Insert Record'
FROM inserted i
WHERE i.verification_id IS NOT NULL
END
As an aside, and strictly speaking, your original trigger will log one row, not necessarily the first.
I am trying to copy data from 2 tables linked by a foreign key on one server and then inserted them into the master database on another server.
The first table will generate a new IDENTITY column and then I want to store this in a variable and insert it into the 2nd table.
I have tried both using internal inserted tables and also SCOPE_IDENTITY() but receive errors that this is not allowed on a REMOTE server
DECLARE
#VisitSourceId int,
#SiteDomainId int,
#trpUTMid bigint,
#FlightPlus bit,
#StartDate datetime,
#CountryId int,
#ProvinceId int,
#Locationid int,
#PlaceId int,
#EstabId int,
#CheckInDate smalldatetime,
#CheckOutDate smalldatetime,
#Rooms int,
#Room1Adults int,
#Room1Children int,
#Room2Adults int,
#Room2Children int,
#Room3Adults int,
#Room3Children int,
#OutcomeDate datetime,
#OutcomeId smallint,
#HotelsFound smallint,
#Notes nvarchar,
#id bigint
DECLARE c CURSOR STATIC FOR
SELECT t.VisitSourceId, t.SiteDomainId, t.trpUTMid, t.FlightPlus, t.StartDate, t.CountryId, t.ProvinceId, t.Locationid,
t.PlaceId, t.EstabId, t.CheckInDate, t.CheckOutDate, t.Rooms, t.Room1Adults, t.Room1Children, t.Room2Adults, t.Room2Children, t.Room3Adults,
t.Room3Children, tc.OutcomeDate, tc.OutcomeId, tc.HotelsFound, tc.Notes
FROM [MLT_VisitTracking].[dbo].TrackingAcomSearches_tbl t
INNER JOIN TrackingAcomSearchesOutcome_tbl tc
ON t.trpUTMid = tc.trpUTMid
open c
FETCH FIRST FROM c INTO #VisitSourceId, #SiteDomainId, #trpUTMid, #FlightPlus, #StartDate, #CountryId, #ProvinceId, #Locationid,
#PlaceId, #EstabId, #CheckInDate, #CheckOutDate, #Rooms, #Room1Adults, #Room1Children, #Room2Adults, #Room2Children, #Room3Adults,
#Room3Children, #OutcomeDate, #OutcomeId, #HotelsFound, #Notes
while ##fetch_status=0
begin
DECLARE #TmpTable TABLE (ID BIGINT)
INSERT INTO [YAZOO].[MLT_VisitTracking].[dbo].TrackingAcomSearches_tbl
(VisitSourceId, SiteDomainId, trpUTMid, FlightPlus, StartDate, CountryId, ProvinceId, Locationid,
PlaceId, EstabId, CheckInDate, CheckOutDate, Rooms, Room1Adults, Room1Children, Room2Adults, Room2Children, Room3Adults,
Room3Children)
OUTPUT inserted.searchid into #TmpTable
SELECT #VisitSourceId, #SiteDomainId, #trpUTMid, #FlightPlus, #StartDate, #CountryId, #ProvinceId, #Locationid,
#PlaceId, #EstabId, #CheckInDate, #CheckOutDate, #Rooms, #Room1Adults, #Room1Children, #Room2Adults, #Room2Children, #Room3Adults,
#Room3Children
select top 1 #id = searchid from #tmptable
INSERT INTO [YAZOO].[MLT_VisitTracking].[dbo].TrackingAcomSearchesOutcome_tbl
(SearchId,
trpUTMid,
OutcomeDate,
OutcomeId,
HotelsFound,
Notes)
SELECT #id,
#trpUTMid,
#OutcomeDate,
#OutcomeId,
#HotelsFound,
#Notes
DELETE FROM [MLT_VisitTracking].[dbo].TrackingAcomSearches_tbl WHERE trpUTMid=#trpUTMid
DELETE FROM [MLT_VisitTracking].[dbo].TrackingAcomSearchesOutcome_tbl WHERE trpUTMid=#trpUTMid
FETCH NEXT FROM c INTO #VisitSourceId, #SiteDomainId, #trpUTMid, #FlightPlus, #StartDate, #CountryId,
#ProvinceId, #Locationid, #PlaceId, #EstabId, #CheckInDate, #CheckOutDate, #Rooms, #Room1Adults, #Room1Children,
#Room2Adults, #Room2Children, #Room3Adults, #Room3Children, #OutcomeDate, #OutcomeId, #HotelsFound, #Notes
end
close c
deallocate c
##IDENTITY and SCOPE_IDENTITY() are local
are you using a linked server?
check this:
get ##Identity from another server(linked server)
To resolve the issue I finally created the script on the target server as a stored procedure, then I could use scope identity. The performance also improved massively, I then configured a new linked server with RPC out enabled and called the procedure remotely. It is not an elegant solution, but its only temporary