Cannot insert explicit value for identity column - sql-server

I am migrating my application form one database to other with keeping table structure as it is. I am creating same tables in new table and inserted value using db link.
I am getting error message like "Cannot insert explicit value for identity column in table 'XYZ' when IDENTITY_INSERT is set to OFF." because table XYZ have ScreenConfigSettingAccessId as an identity column
Below is the script I am using for creating table and inserting value
CREATE TABLE [dbo].[XYZ](
[ScreenConfigSettingAccessId] [int] IDENTITY(1,1) NOT NULL,
[APP_ID] [int] NOT NULL,
[ScreenConfigSettingId] [int] NOT NULL,
[RSRC_ID] [char](20) NOT NULL)
)
INSERT INTO [dbo].[XYX]
(
[ScreenConfigSettingAccessId] ,
[APP_ID] ,
[ScreenConfigSettingId] ,
[RSRC_ID]
)
SELECT
[ScreenConfigSettingAccessId] ,
[APP_ID] ,
[ScreenConfigSettingId] ,
[RSRC_ID]
FROM [olddatabase].[database name].[dbo].[XYX]
in old table the value of ScreenConfigSettingAccessId is 3 and 4.
I want to inset the same data which old table have so set IDENTITY_INSERT to ON and tried but it still not allowing to insert.
Looking for you suggestions

You need to specify the table. Check out the command syntax in SQL Books Online: SQL 2000 or SQL 2012 (the syntax hasn't changed).

Related

Getting an "Invalid object name" error in ADS after creating a new table

I'm working on a new Jupyter Notebook, using SQL as the Kernel, to create a new table, populate it with a couple records, etc., then drop the table. I've written the CREATE TABLE DDL, then ran it. However, when I ran it in ADS it gave me an error on the table name ("Invalid object name ") and each column in the new table ("Invalid column name "). But it created the table, nonetheless. Huh? What's going on?
I've looked for similar questions posted here on SO, but none of the match my situation. For example, one of them the user had created the table as one name, but then tried to do a SELECT against a different table name, that was slightly different from the one they created. That's not the case for me. Here's the SQL DDL for creating the table:
IF OBJECT_ID('[dbo].[Bozo]', 'U') IS NOT NULL
DROP TABLE [dbo].[Bozo]
GO
-- Create the table in the specified schema
CREATE TABLE [dbo].[Bozo]
(
[Id] INT NOT NULL PRIMARY KEY, -- Primary Key column
[FirstName] NVARCHAR(50) NOT NULL,
[LastName] NVARCHAR(50) NOT NULL,
-- Specify more columns here
Bool1 BIT DEFAULT 1,
Bool2 BIT DEFAULT 1,
BoolValue AS Bool1 & Bool2
);
GO
And here's my SQL INSERT statements:
NSERT INTO Bozo (FirstName, LastName)
VALUES ('George', 'Washington');
INSERT INTO Bozo (FirstName, LastName, Bool2)
VALUES ('John', 'Adams', 0);
I discovered that the SQL Script that Azure Data Studio uses to create a new table does not define the Id column as an IDENTITY column. Changing that fixed the issue, so now it is:
IF OBJECT_ID('[dbo].[Bozo]', 'U') IS NOT NULL
DROP TABLE [dbo].[Bozo]
GO
-- Create the table in the specified schema
CREATE TABLE [dbo].[Bozo]
(
[Id] INT IDENTITY(1,1) NOT NULL PRIMARY KEY, -- Primary Key column
[FirstName] NVARCHAR(50) NOT NULL,
[LastName] NVARCHAR(50) NOT NULL,
-- Specify more columns here
Bool1 BIT DEFAULT 1,
Bool2 BIT DEFAULT 1,
BoolValue AS Bool1 & Bool2
);
GO

Recursive OR statement SQL Server 2016

I am looking at creating a relatively simple insert statement that inserts a new record if there are any changes to a table. Issue i have is there are over 600 columns that would need to be checked.
More details: the main reporting table is updated every 15 minutes from the front end application using a SQL process to push the changes, however it over-writes the data and doesn't maintain a change log. I have no control over any of this.
Second table (my table) is a DWH table, which will create an audit of changes. So I use an inner join where t1.AccountNo = t2.AccountNo and t1.Field1 <> t.2Field1 then add an OR and add the next field t1.AccountNo = t2.AccountNo and t1.Field2 <> t.2Field2 .
Is there a better way to get the desired result given the number of columns?
You could try a different approach.
Create a trigger on the main table for update and delete.
This trigger copies the data which is already in the table to your dwh table before the data has changed.
create Trigger [nameupdate] on [yourtable] after update
as
insert into [dwh]
select
getdate() as [ChangeDate]
,'update' as [Action]
,SYSTEM_USER as [User]
,d.[ID]
,d.[...]
from deleted d
GO
same for delete
create Trigger [namedelete] on [yourtable] after delete
[...]
my dwh table has 3 additional columns for tracking and contains all columns from main table.
CREATE TABLE [dwh](
[ID] [int] IDENTITY(1,1) NOT NULL Primary key,
[ChangeDate] [datetime] NOT NULL,
[Action] [varchar](50) NOT NULL,
[User] [nvarchar](128) NOT NULL,
[...]

How to update a table if a column exists in SQL Server?

I have a table MyTable created by
CREATE TABLE MyTable
(
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[Type] [int] NOT NULL,
[CreatedDate] [datetime] NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
)
I want to check if a column exists in my table, and if it does, I want to copy the data to a different column, then drop the old column, like this:
IF (SELECT COLUMNPROPERTY(OBJECT_ID('MyTable'), 'Timestamp', 'Precision')) IS NOT NULL
BEGIN
UPDATE [dbo].[MyTable]
SET [CreatedDate] = [Timestamp]
ALTER TABLE [dbo].[MyTable]
DROP COLUMN [Timestamp]
END
GO
However, when I try to run this I get an error:
Invalid column name 'Timestamp'
How can I accomplish what I'm trying to do?
This is a compilation issue.
If the table doesn't exist when you compile the batch all works fine as the statements referencing the table are subject to deferred compile. However for a preexisting table you will hit this problem as it tries to compile all statements and balks at the non existent column.
You can push the code into a child batch so it is only compiled if that branch is hit.
IF (SELECT COLUMNPROPERTY(OBJECT_ID('MyTable'), 'Timestamp', 'Precision')) IS NOT NULL
BEGIN
EXEC('
UPDATE [dbo].[MyTable]
SET [CreatedDate] = [Timestamp]
ALTER TABLE [dbo].[MyTable]
DROP COLUMN [Timestamp]
')
END
GO
If you are just trying to rename the column
EXEC sys.sp_rename 'dbo.MyTable.[TimeStamp]' , 'CreatedDate', 'COLUMN'
Would be easier though (from a position where the CreatedDate column doesn't exist).
You have to first create the [Timestamp] column with an ALTER TABLE statement.
Then the rest should run.
EDIT based on comment (I know this info is duplicated elsewhere on SO, but I couldn't find it):
Ok, the IF condition in SQL Server unfortunately does not allow you to ignore code that does not parse. What is happening is that SQL Server is looking at your command, and parsing every statement to make sure it is valid.
When it does this, SQL Server isn't smart enough to figure out that the invalid statement (the UPDATE that requires the presence of [TimeStamp]) will not be reached if there is no [TimeStamp].
In other words, you can't write a SQL command that expects a column that doesn't exist EVEN IF you nest that command in an IF condition that won't be reached. SQL Server will parse the entire statement and not allow it to run BEFORE it tests the IF condition.
A commonly used Work arounds for this is Dynamic SQL, which SQL Server can't pre-parse, so it won't try.

How to design audit dimension in the data mart using SQL Server 2012

Goal
I aim to create SSIS (ETL) Template that enables audit functionality (Audit Dimension). I've discovered a few ways to implement audit dimension that are described below with some reference links below:
SEQUENCE
Primary Key
Best way to get identity of inserted row?
Environment:
There are millions of rows in a fact tables and packages run a few
times a day.
Incremental ETL gets thousands of rows.
SQL Server 2012 BI edition is used for the BI solution.
Simplified Schema of DimAudit table:
CREATE TABLE [dw].[DimAudit] (
[AuditKey] [int] IDENTITY(1 ,1) NOT NULL,
[ParentAuditKey] [int] NOT NULL,
[TableName] [varchar] (50) NOT NULL DEFAULT ('Unknown'),
[PackageName] [varchar] (50) NOT NULL DEFAULT ('Unknown'),
[ExecStartDate] [datetime] NOT NULL DEFAULT ( getdate()),
[ExecStopDate] [datetime] NULL,
[SuccessfulProcessingInd] [char] (1) NOT NULL DEFAULT ('N'),
CONSTRAINT [PK_dbo.DimAudit] PRIMARY KEY CLUSTERED
(
[AuditKey] ASC
)
) ON [PRIMARY]
ALTER TABLE [dw].[DimAudit] WITH CHECK ADD CONSTRAINT [FK_DimAudit_ParentAuditKey] FOREIGN KEY( [ParentAuditKey])
REFERENCES [dw]. [DimAudit] ( [AuditKey])
GO
ALTER TABLE [dw].[DimAudit] CHECK CONSTRAINT [FK_DimAudit_ParentAuditKey]
GO
Primary Key Option:
Primary key is generated in the audit table and then AuditKey is queried.
Task: Master SQL Audit Generates Key (SQL Task)
INSERT INTO [dw].[DimAudit]
(ParentAuditKey
,[TableName]
,[PackageName]
,[ExecStartDate]
,[ExecStopDate]
,[SuccessfulProcessingInd])
VALUES
(1
,'Master Extract Package'
,?
,?
,?
,'N')
SELECT AuditKey
FROM [dw].[DimAudit]
WHERE TableName = 'Master Extract Package' and ExecStartDT = ?
/*
Last Parameter: ParameterSystem::StartTime
Result Set populates User::ParentAuditKey
*/
Task: Master SQL Audit End (SQL Task)
UPDATE [dw]. [DimAudit]
SET ParentAuditKey = AuditKey
,ExecStopDT = SYSDATETIME()
,SuccessfulProcessingInd= 'Y'
WHERE AuditKey = ?
/*
Parameter: User::ParentAuditKey
*/
SEQUENCE Option:
The sequence option does not select primary key (AuditKey) but uses logic below to create next available AuditKey.
CREATE SEQUENCE dbo . AuditID as INT
START WITH 1
INCREMENT BY 1 ;
GO
DECLARE #AuditID INTEGER ;
SET #AuditID = NEXT VALUE FOR dbo. AuditID ;
Best way to get identity of inserted row?
It feels risky using identity options as ETL packages could be executed in parallel.
Question
What is the recommended practice for audit dimension table and managing keys?
Sequence & primary key options do the job; however, I have concerns about the selecting primary key option because package could be executed the same millisecond (in theory) and therefore, a few primary keys would exist. So, Sequence sounds like the best option.
Is anything better I could do to create Audit Dimension for a data mart?
You could use the OUTPUT syntax:
INSERT INTO [dw].[DimAudit]
(ParentAuditKey
,[TableName]
,[PackageName]
,[ExecStartDate]
,[ExecStopDate]
,[SuccessfulProcessingInd])
OUTPUT inserted.AuditKey
VALUES
(1
,'Master Extract Package'
,?
,?
,?
,'N')
or SCOPE_IDENTITY() which is what I'm personally using:
INSERT INTO Meta.AuditDim (
Date,
UserName,
Source,
SourceType,
AuditType,
ExecutionId,
ExecutionHost,
ParentAuditKey,
FileID
)
VALUES (
GETDATE(),
CURRENT_USER,
#Source,
#SourceType,
#AuditType,
#ExecutionId,
#ExecutionHost,
#ParentAuditKey,
#FileID
);
SELECT AuditKey FROM Meta.AuditDim WHERE AuditKey = SCOPE_IDENTITY();

SQL insert default value

SQL Server 2000
Say if I have a table like
CREATE TABLE [Message] (
[MessageIdx] [int] IDENTITY (1, 1) NOT NULL ,
[Message] [varchar] (1024) COLLATE Latin1_General_CI_AS NOT NULL ,
[column1] ... ,
[column2] ... ,
... ,
[ValidUntil] [datetime] NULL ,
CONSTRAINT [PK_Message] PRIMARY KEY CLUSTERED
(
[MessageIdx]
) WITH FILLFACTOR = 90 ON [PRIMARY]
) ON [PRIMARY]
GO
Since there're too many columns, so I am trying to insert value without specify column names explicitly. I want to insert a new row with all columns except 'MessageIdx' and 'ValidUntil' not specified. Therefore, I definitely don't want to type all column names.
I tried below statement but it causes error. How can I do that? Thanks.
insert into message values (DEFAULT,'blah',something, ..., DEFAULT);
EDIT: AFAIN, SQL 2005 server you can skip the identity column when inserting. So that will be
insert into message values ('blah',something, ..., DEFAULT);
But is there any work around for SQL server 2000?
you have to specify column names if you use set identity_insert
but you can do this
set identity_insert caconfig..fxmessage on;
insert into message (MessageIdx,[Message],[ValidUntil)
values (1,'blah',GETDATE());
set identity_insert caconfig..fxmessage off;
I assume what you really want is this, it will generate the identity value for you
insert into message ([Message],[ValidUntil) values ('blah',GETDATE());
Don't be lazy. Do it the correct way, which is to specify the column list (excluding the identity column).
Use getdate(), and for IDENTITY columns (if using uniqueidentifier which I see you're not), you can use newid(), and set them in the design-view of the table in the default value. After that you'd simply go:
INSERT INTO Message (Message) VALUES ('blah');

Resources