Expecting to drop and re-create if the table is exist. Actual is instead of dropping the table, inserting data again on to the table.
BEGIN
PRINT N'Seeding [Proj].[UserTable]...';
SET NOCOUNT ON
--
-- BEGIN SEED DATA SECTION
--
IF OBJECT_ID('#tempdb..#SeedData') IS NOT NULL DROP TABLE #SeedData
SET NOCOUNT ON
CREATE TABLE #SeedData (
[UserName] nvarchar(50) NULL,
[CreatedById] [bigint] NULL,
[CreatedDate] [datetimeoffset](7) NULL
)
INSERT INTO #SeedData SELECT N'UserA',-1,getdate()
...
--
-- END SEED DATA SECTION
--
SET NOCOUNT OFF
INSERT INTO [Proj].[UserTable] (
[UserName],
[CreatedById],
[CreatedDate]
)
SELECT seed.[UserName]
,seed.[CreatedById]
,seed.[CreatedDate]
FROM #SeedData seed
DROP TABLE #SeedData
SET NOCOUNT OFF
END
GO
Tried codes:
- IF OBJECT_ID('#SeedData', 'U') IS NOT NULL DROP TABLE #SeedData
- IF OBJECT_ID('tempdb..#SeedData', 'U') IS NOT NULL DROP TABLE #SeedData
use
IF OBJECT_ID('tempdb..#SeedData') is not null
drop table #seeddata
I am not able to repro the issue,even passing the table parameter..
Test :
create table #test
(
id int
)
select * from tempdb.sys.objects--you can see table
if object_id('tempdb..#test','u') is not null
drop table #test
select * from tempdb.sys.objects--you can't see table
Remove the hash in front of '#temp db..'
BEGIN
PRINT N'Seeding [Proj].[UserTable]...';
SET NOCOUNT ON
--
-- BEGIN SEED DATA SECTION
--
IF OBJECT_ID('tempdb..#SeedData') IS NOT NULL DROP TABLE #SeedData
SET NOCOUNT ON
CREATE TABLE #SeedData (
[UserName] nvarchar(50) NULL,
[CreatedById] [bigint] NULL,
[CreatedDate] [datetimeoffset](7) NULL
)
INSERT INTO #SeedData SELECT N'UserA',-1,getdate()
...
--
-- END SEED DATA SECTION
--
SET NOCOUNT OFF
INSERT INTO [Proj].[UserTable] (
[UserName],
[CreatedById],
[CreatedDate]
)
SELECT seed.[UserName]
,seed.[CreatedById]
,seed.[CreatedDate]
FROM #SeedData seed
DROP TABLE #SeedData
SET NOCOUNT OFF
END
GO
Try this instead for the drop table statement, replacing [Database].[Schema].[TableName] for the object you're trying to drop.
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[Database].[Schema].[TableName]') AND type in (N'U'))
DROP TABLE [Database].[Schema].[TableName]
GO
Related
I have 2 tables and I want table 1 to have a trigger that insert or update in table 2, but I'm not sure how to do that.
Table 1:
CREATE TABLE [dbo].[DevicePorts](
[ID] [int] IDENTITY(1,1) NOT NULL,
[IsInUse] [bit] NOT NULL,
)
Table 2:
CREATE TABLE [dbo].[DevicePortActivities](
[ID] [uniqueidentifier] NOT NULL,
[StartTime] [datetimeoffset](7) NOT NULL,
[EndTime] [datetimeoffset](7) NULL,
[FK_DevicePortID] [int] NOT NULL FOREIGN KEY REFERENCES DevicePorts(ID),
)
Start of my trigger:
CREATE TRIGGER PortInUse
ON DevicePorts
AFTER UPDATE
AS BEGIN
SET NOCOUNT ON;
IF UPDATE (IsInUse)
BEGIN
IF IsInUse = 1
THEN
INSERT INTO [dbo].[DevicePortActivities]
(
[ID]
,[StartTime]
,[EndTime]
,[FK_DevicePortID]
)
VALUES
(
NEWID(),
SYSDATETIMEOFFSET(),
null,
<DevicePortID>
)
ELSE
UPDATE [dbo].[DevicePortActivities]
SET EndTime = SYSDATETIMEOFFSET()
WHERE FK_DevicePortID = <DevicePortID> AND EndTime is null
END
END
END
GO
What I'm trying to do is when 'IsInUse' is modified it should insert a row into 'DevicePortActivities' or update.
Conditions are, if 'IsInUse' is true then it should insert a record, if it's false it should update the last record where 'EndTime' is null.
You need to treat inserted as a table. I'd suggest looking at MERGE for this (because different rows may have had different changes applied by a single UPDATE).
Something like:
CREATE TRIGGER PortInUse
ON DevicePorts
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
MERGE INTO [dbo].[DevicePortActivities] t
USING (select i.ID,i.IsInUse as NewUse,d.IsInUse as OldUse
from inserted i inner join deleted d on i.ID = d.ID) s
ON
t.FK_DevicePortID = s.ID
WHEN MATCHED AND t.EndTime is null AND NewUse = 0 and OldUse = 1
THEN UPDATE SET EndTime = SYSDATETIMEOFFSET()
WHEN NOT MATCHED AND NewUse = 1 and OldUse = 0
THEN INSERT ([ID]
,[StartTime]
,[EndTime]
,[FK_DevicePortID])
VALUES (NEWID(),
SYSDATETIMEOFFSET(),
null,
s.ID);
END
I found a solution for my question
CREATE TRIGGER [dbo].[PortInUse]
ON [dbo].[DevicePorts]
AFTER UPDATE
AS BEGIN
SET NOCOUNT ON;
IF UPDATE (IsInUse)
BEGIN
DECLARE #IsInUse bit;
DECLARE #PortID int;
SELECT #IsInUse = i.IsInUse FROM inserted i;
SELECT #PortID = i.ID FROM inserted i;
IF (#IsInUse = 1)
INSERT INTO [dbo].[DevicePortActivities]
(
[ID]
,[StartTime]
,[EndTime]
,[FK_DevicePortID]
)
VALUES
(
NEWID(),
SYSDATETIMEOFFSET(),
null,
#PortID
);
ELSE
UPDATE [dbo].[DevicePortActivities]
SET EndTime = SYSDATETIMEOFFSET()
WHERE FK_DevicePortID = #PortID AND EndTime is null;
END
END
I'm not sure if there is a better way to do this, but it's working.
Consider the following table
CREATE TABLE [dbo].[Numbers]
(
[Id] [INT] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]
How do I populate it?
If I add a column (text nchar(20) say) then I can populate it with:
insert into numbers (text) values ('')
but if there are no other columns besides the identity, what do I do?
insert into numbers ( ) values ( )
This throws an error
Incorrect syntax near ')'.
I want to use this for a find the missing sequence number problem.
Specify DEFAULT VALUES:
INSERT INTO dbo.Numbers DEFAULT VALUES;
Or even you can use SET IDENTITY_INSERT:
SET IDENTITY_INSERT YourTable ON;
GO
INSERT INTO YourTable (IdentityColumn) VALUES
(1),
(2),
(3);
GO
SET IDENTITY_INSERT YourTable OFF;
Sample:
CREATE TABLE [dbo].[Numbers](
[Id] [int] IDENTITY(1,1) NOT NULL
) ON [PRIMARY];
DECLARE #Start INT=1;
DECLARE #End INT=100;
SET IDENTITY_INSERT [dbo].[Numbers] ON;
WITH Gen AS (
SELECT #Start AS Num
UNION ALL
SELECT Num + 1 FROM Gen WHERE Num + 1 <= #End
)
INSERT INTO [dbo].[Numbers] (Id)
SELECT Num
FROM Gen
OPTION (maxrecursion 100);
SET IDENTITY_INSERT [dbo].[Numbers] OFF;
SELECT *
FROM [dbo].[Numbers];
I have a trigger for auditing record insert,update and delete. My code is
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[mytable_insertafter_audit]
ON [dbo].[mytable]
AFTER INSERT, DELETE, UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Action as char(1);
SET #Action = (CASE WHEN EXISTS(SELECT * FROM INSERTED)
AND EXISTS(SELECT * FROM DELETED)
THEN 'U' -- Set Action to Updated.
WHEN EXISTS(SELECT * FROM INSERTED)
THEN 'I' -- Set Action to Insert.
WHEN EXISTS(SELECT * FROM DELETED)
THEN 'D' -- Set Action to Deleted.
ELSE NULL -- Skip. It may have been a "failed delete".
END)
IF (#Action = 'I')
BEGIN
INSERT INTO audit_trg
SELECT
lr.sanction_status, i.sanction_status,
GETDATE(), lr.id, 'mytable', #Action
FROM
mytable lr
INNER JOIN
INSERTED i ON i.id = lr.id
END
ELSE IF (#Action = 'U')
BEGIN
INSERT INTO audit_trg
SELECT
i.sanction_status, lr.sanction_status,
GETDATE(), lr.id, 'mytable', #Action
FROM
mytable lr
INNER JOIN
DELETED i ON i.id = lr.id
END
ELSE
BEGIN
INSERT INTO audit_trg
SELECT
lr.sanction_status, i.sanction_status,
GETDATE(), lr.id, 'mytable', #Action
FROM
mytable lr
INNER JOIN
DELETED i ON i.id = lr.id
END
END
and audit_trg table
CREATE TABLE [dbo].[audit_trg]
(
[id] [int] IDENTITY(1,1) NOT NULL,
[old_status] [varchar](50) NULL,
[new_status] [varchar](50) NULL,
[u_datetime] [datetime] NULL,
[ref_id] [int] NULL,
[table_name] [varchar](50) NULL,
[actions] [varchar](50) NULL,
CONSTRAINT [PK_audit_trg]
PRIMARY KEY CLUSTERED ([id] ASC)
) ON [PRIMARY]
but I get error after some inserted that is
The target table 'dbo.mytable' of the DML statement cannot have
any enabled triggers if the statement contains an OUTPUT clause
without INTO clause.
I have a table that looks like this :
CREATE TABLE [dbo].[akut_prioritering]
(
[behandling_id] [int] NOT NULL,
[akutstatus] [int] NOT NULL,
[nasta_dag] [bit] NOT NULL,
[sort_order] [bigint] NOT NULL,
[rowversion] [timestamp] NOT NULL,
CONSTRAINT [XPKakut_prioritering]
PRIMARY KEY CLUSTERED ([behandling_id] ASC)
) ON [PRIMARY]
And then I have this stored procedure that tries to update rows in this table :
ALTER PROCEDURE [dbo].[akutlistaSave]
#behandlingSortOrder dbo.akutlista_sortorder_tabletype READONLY
AS
BEGIN
SET NOCOUNT ON;
DECLARE #behandlingId INT;
DECLARE #sortOrder BIGINT;
DECLARE #rowversion ROWVERSION;
DECLARE sortOrderCursor CURSOR LOCAL SCROLL STATIC FOR
SELECT behandling_id, sort_order FROM #behandlingSortOrder
OPEN sortOrderCursor
BEGIN TRAN
FETCH NEXT FROM sortOrderCursor INTO #behandlingId, #sortOrder, #rowversion
WHILE ##FETCH_STATUS = 0
BEGIN
IF EXISTS(SELECT *
FROM akut_prioritering ap
WHERE ap.behandling_id = #behandlingId
AND ap.rowversion = #rowversion)
BEGIN
UPDATE akut_prioritering
SET sort_order = #sortOrder
WHERE behandling_id = #behandlingId;
END
ELSE
BEGIN
RAISERROR ('Rowversion not correct.', 16, 1);
END
FETCH NEXT FROM sortOrderCursor INTO #behandlingId, #sortOrder, #rowversion
END
CLOSE sortOrderCursor
SELECT
ap.behandling_id, ap.rowversion
FROM
akut_prioritering ap
INNER JOIN
#behandlingSortOrder bso ON ap.behandling_id = bso.behandling_id;
DEALLOCATE sortOrderCursor
END
The inparameter type looks like this :
CREATE TYPE [dbo].[akutlista_sortorder_tabletype] AS TABLE
(
[behandling_id] [int] NULL,
[sort_order] [bigint] NULL,
[rowversion] [timestamp] NULL
)
When running this I get a SqlException :
Cannot insert an explicit value into a timestamp column. Use INSERT with a column list to exclude the timestamp column, or insert a DEFAULT into the timestamp column.
From what I understand the rowversion column should be updated with a new value automatically, there is no reason in my case to set it manual.
You can't set the rowversion value in dbo.akutlista_sortorder_tabletype because it is not updateable: it is auto generated
However, rowversion (a.k.a deprecated timestamp) is simply a (var)binary(8) with some special rules. You can define and set a (var)binary(8) in dbo.akutlista_sortorder_tabletype and compare on that in the UPDATE
From the first link
A nonnullable rowversion column is semantically equivalent to a binary(8) column. A nullable rowversion column is semantically equivalent to a varbinary(8) column.
It looks like you are trying to insert a timestamp value in a custom table type and then passing that to your stored procedure. As your error suggests, you cannot insert explicit timestamp values into timestamp columns.
You will need to find a different way of passing you table values to this stored procedure to work.
I have created a scalar function in SQL Server 2008 and the same I am referring in a computed column in few of my tables. Now I want to alter the function without dropping the table. But it throws an error:
Cannot ALTER 'dbo.GetStatus' because it is being referenced by object
'Order'.
Is is possible to alter the function? Or do I drop and create all dependable table first and then alter the function?
Here is my function:
CREATE FUNCTION [dbo].[GetStatus]
(
#FromDate datetime,
#ToDate datetime
)
RETURNS tinyint
AS
BEGIN
declare #ret tinyint;
if(#FromDate<=GETDATE() and (#ToDate>=GETDATE() or #ToDate is null))
set #ret= 1
else
set #ret= 0
return #ret
END
And it is referring in a table:
CREATE TABLE [dbo].[Order](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](200) NOT NULL,
[EffectiveFromDate] [datetime] NOT NULL,
[EffectiveToDate] [datetime] NULL,
[Status] AS ([dbo].[GetStatus]([EffectiveFromDate],[EffectiveToDate]))
)
This is by design. You should first drop all defaults/constraints, then alter your function and the add those constraints back. No need to drop the tables.
But you can work around this by the following trick:
add intermediate function that will call your actual function;
alter computed columns to call intermediate function instead of actual.
Example:
CREATE FUNCTION dbo.fnActual ( #p INT )
RETURNS INT
AS
BEGIN
RETURN #p + 1
END
GO
CREATE FUNCTION dbo.fnIntermediate ( #p INT )
RETURNS INT
AS
BEGIN
RETURN dbo.fnActual(#p)
END
GO
CREATE TABLE TestTable(id INT, fn AS dbo.fnIntermediate(id))
GO
Insert some value:
INSERT INTO dbo.TestTable VALUES ( 1 )
SELECT * FROM dbo.TestTable --selects 2
--throws exception
ALTER FUNCTION dbo.fnIntermediate ( #p INT )
RETURNS INT
AS
BEGIN
RETURN dbo.fnActual(#p)
END
GO
--succseeds
ALTER FUNCTION dbo.fnActual ( #p INT )
RETURNS INT
AS
BEGIN
RETURN #p + 2
END
GO
SELECT * FROM dbo.TestTable --selects 3
ALTER TABLE [dbo].[Order]
DROP COLUMN [Status]
GO
ALTER FUNCTION [dbo].[GetStatus] ...
GO
ALTER TABLE [dbo].[Order]
ADD [Status] AS ([dbo].[GetStatus]([EffectiveFromDate],[EffectiveToDate]))
GO
or even
ALTER TABLE [dbo].[Order]
DROP COLUMN [Status]
GO
ALTER TABLE [dbo].[Order]
ADD [Status] AS CAST(CASE WHEN [EffectiveFromDate] <= GETDATE() AND ([EffectiveToDate] >= GETDATE() OR [EffectiveToDate] IS NULL) THEN 1 ELSE 0 END as tinyint)
GO