SQL Server IDENTITY column - sql

How can I modify this command in order to have an identity column which has five digits integer like 00000 and start from 00001 ?
CREATE TABLE [dbo].[Company]
(
[CompanyId] [bigint] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](200) NOT NULL
)

An integer does not have any leading 0 by itself. It is a formatting issue to deal with when converting the integer to a string for displaying.
If you really, really need to be able to present such a string right out of SQL, you can do it with a computed column:
CREATE TABLE [dbo].[Company](
[CompanyId] [bigint] IDENTITY(1,1) NOT NULL,
[FormattedCompanyId] AS RIGHT('0000'+ CONVERT(VARCHAR,Num),5),
[Name] nvarchar NOT NULL,
I would never use that solution myself though, formatting doesn't belong in the data store.

You need to add the leading zeros yourself. As a solution you can add an other colomn named say "formatedID" and update it with an "after insert trigger" with the value from the identity column and formatted with the leading zeros you want to.
Example :
CREATE TABLE [dbo].[Company]
(
[CompanyId] [bigint] IDENTITY(1,1) NOT NULL,
[FormattedID] [VARCHAR(20)],
[Name] [nvarchar](200) NOT NULL
)
CREATE TRIGGER ON [dbo].[Company]
FOR INSERT
AS
BEGIN
UPDATE [dbo].[Company]
FROM inserted
SET FormattedID = RIGHT('0000'+ CONVERT(VARCHAR, [dbo].[Company].CompanyId),5)
WHERE dbo.Company.CompanyId = inserted.CompanyId
END

Related

Replacing a trigger with a stored procedure

I'm trying to replace a trigger statement with a stored procedure since enabled triggers are not allowed when using the tables in microsoft powerapps.
Simplified, I have to tables:
KPI_Dim (KPI_ID [PK] , KPIName, KPIGroup...)
KPICurrent_Fact (KPI_key [FK i.e KPI_Dim[KPI_ID], KPICurrent_ID, KPI_Value...)
Currently, for every new record in KPI_Dim my trigger adds a new row in KPICurrent_Fact with the FK and an autoincremented PK. The rest of the columns e.g. KPI_Value are supposed to be empty.
My simple trigger looks like this:
CREATE TRIGGER [dbo].[trg_insert_newKPI]
ON [dbo].[KPI_Dim]
FOR INSERT AS
INSERT INTO KPICurrent_Fact (KPI_key)
SELECT KPI_ID
FROM INSERTED
Now, I want to create a stored procedure that can achieve exactly the same. I have tried to find a solution myself but I'm new to stored procedures and could not find anything that would replicate a trigger.
I'm using SSMS v.18.4.
Thank you for any suggestions.
EDIT
Added Table creation and insert into statement code.
/* Create KPI_Dim table*/
CREATE TABLE [dbo].[KPI_Dim](
[KPI_ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[KPIName] [varchar](200) NOT NULL,
[KPIDescription] [varchar](500) NULL,
[KPIGroup] [varchar](100) NOT NULL,
[KPISubGroup] [varchar](100) NULL,
[KPIOwner] [varchar] (50) NOT NULL,
[DateCreated] DATETIME NULL DEFAULT(GETDATE())
)
/* Example data */
INSERT INTO [dbo].[KPI_Dim]
(
KPIName,
KPIDescription,
KPIGroup,
KPISubGroup,
KPIOwner
)
VALUES
('TestKPIName','testtest','TestGroup', 'TestSubGroup', 'TestOwner');
You can go for OUTPUT Clause and insert into table variable. From the table variable, you can insert into fact table.
CREATE TABLE [dbo].[KPI_Dim](
[KPI_ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[KPIName] [varchar](200) NOT NULL,
[KPIDescription] [varchar](500) NULL,
[KPIGroup] [varchar](100) NOT NULL,
[KPISubGroup] [varchar](100) NULL,
[KPIOwner] [varchar] (50) NOT NULL,
[DateCreated] DATETIME NULL DEFAULT(GETDATE())
)
CREATE TABLE dbo.KPI_Fact
(
[KPI_ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[KPIDIMID] INT NULL FOREIGN KEY references [dbo].[KPI_Dim]([KPI_ID])
)
DECLARE #inserted table(KPI_DIMID INT)
INSERT INTO [dbo].[KPI_Dim]
(
KPIName,
KPIDescription,
KPIGroup,
KPISubGroup,
KPIOwner
)
OUTPUT inserted.KPI_ID INTO #inserted
VALUES
('TestKPIName','testtest','TestGroup', 'TestSubGroup', 'TestOwner');
INSERT INTO dbo.KPI_Fact([KPIDIMID])
SELECT * FROM #inserted
KPI_ID
KPIDIMID
1
1

Define column name which only takes 10 digit number in SQL

I have the following code in for a SQL TABLE
CREATE TABLE [dbo].[Table_1](
[ID] [int] NULL,
[StudentID] [nvarchar](10) NULL,
[Name] [nvarchar](50) NULL,
[Address] [nvarchar](500) NULL,
[Phone] [nvarchar](10) NULL
) ON [PRIMARY]
GO
But I can insert any value for StudentID. I want to insert 10 digit number, if it is less/greater then 10 digit it shouldn't take the value. Can anyone help me with this since I am new to SQL. Thank you
If you want StudentId to be ten digits, you can define a check constraint. In SQL Server, this would look like:
alter table table_1 add constraint chk_table_1_student_id
check (student_id like '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]');
If you don't like counting expressions in strings, you can also specify:
alter table table_1 add constraint chk_table_1_student_id
check (len(student_id) = 10 and student_id not like '%[^0-9]%');
That is, it has a length of 10 and no non-digit characters.

How to convert numeric to nvarchar in SQL Server?

Consider the following table. I use a trigger to add to the table. In the column of converting the number to the string, it fails.
CREATE TABLE [dbo].[tblAIAgent]
(
[AgentCode] [NVARCHAR](10) NOT NULL,
[NationalCode] [BIGINT] NOT NULL
CONSTRAINT [DF_tblAIAgent_NationalCode] DEFAULT ((0)),
[FirstName] [NVARCHAR](50) NOT NULL
CONSTRAINT [DF_tblAIAgent_Name] DEFAULT (''),
[LastName] [NVARCHAR](50) NOT NULL
CONSTRAINT [DF_tblAIAgent_Family] DEFAULT (''),
[IsActive] [BIT] NOT NULL
CONSTRAINT [DF_tblAIAgent_Active] DEFAULT ((1)),
[Counter] [INT] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_tblAIAgent]
PRIMARY KEY CLUSTERED
)
ALTER TRIGGER [dbo].[AgentInsert]
ON [dbo].[tblAIAgent]
INSTEAD OF INSERT
AS
BEGIN
DECLARE #AgentCode NVARCHAR(10)
DECLARE #NationalCode BIGINT
DECLARE #FirstName NVARCHAR(50)
DECLARE #LastName NVARCHAR(50)
DECLARE #IsActive BIT
DECLARE #CounterIs INT
SET #CounterIs = ##IDENTITY
SELECT
#AgentCode = AgentCode,
#NationalCode = NationalCode,
#FirstName = FirstName,
#LastName = LastName,
#IsActive = IsActive
FROM inserted
INSERT INTO tblAIAgent (NationalCode, FirstName, LastName, IsActive, AgentCode)
VALUES (#NationalCode, #FirstName, #LastName, #IsActive, 'Agent_' + CAST(#CounterIs AS NVARCHAR(4)))
END
You have a few problems here:
The ##IDENTITY is a system function contains the last identity value that is generated when an INSERT, SELECT INTO, or BULK COPY statement is completed. If the statement did not affect any tables with identity columns, ##IDENTITY returns NULL. If multiple rows are inserted, generating multiple identity values, ##IDENTITY returns the last identity value generated.
In your case, you have an INSTEAD OF INSERT trigger, so there is no INSERT.
This below query is completely wrong and will gives wrong results, it works as expected only if one row inserted, if there is more than 1 row, then those variables will hold just the values of one row, and you will lose the other values of the other rows, cause the pseudo INSERTED may contains 1 or more rows
select #AgentCode=AgentCode,
#NationalCode=NationalCode,
#FirstName=FirstName,
#LastName=LastName,
#IsActive=IsActive
from inserted
Now, looking to your table, you already have an IDENTITY column, so you don't need to a TRIGGER at all, you can just make a computed column as
CREATE TABLE [dbo].[tblAIAgent](
[AgentCode] AS 'Agent_' + CAST([Counter] AS VARCHAR(10)),
[NationalCode] [bigint] NOT NULL
CONSTRAINT [DF_tblAIAgent_NationalCode] DEFAULT ((0)),
[FirstName] [nvarchar](50) NOT NULL
CONSTRAINT [DF_tblAIAgent_Name] DEFAULT (''),
[LastName] [nvarchar](50) NOT NULL
CONSTRAINT [DF_tblAIAgent_Family] DEFAULT (''),
[IsActive] [bit] NOT NULL
CONSTRAINT [DF_tblAIAgent_Active] DEFAULT ((1)),
[Counter] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_tblAIAgent] PRIMARY KEY ([Counter])
);
UPDATE:
According to your comment "a computed column can no longer be selected as the PK. I want this column to be placed in other relevant tables as a FK.I wrote the trigger to get the column value instead of the computed column so that I can select the column as the primary key". You are trying to make it a PRIMARY KEY so you can do as
CREATE TABLE T(
Counter INT IDENTITY(1,1) NOT NULL,
OtherCol INT,
Computed AS CONCAT('Agent_', CAST(Counter AS VARCHAR(10))) PERSISTED,
CONSTRAINT PKT PRIMARY KEY(Computed)
);
CREATE TABLE TT(
ReferenceComputedColumn VARCHAR(16) NOT NULL,
OtherColumn INT,
CONSTRAINT FK_ReferencedComputedColumn
FOREIGN KEY(ReferenceComputedColumn)
REFERENCES T(Computed)
)
INSERT INTO T(OtherCol) VALUES
(1), (2), (3);
INSERT INTO TT(ReferenceComputedColumn, OtherColumn) VALUES
('Agent_1', 10),
('Agent_3', 20);
SELECT *
FROM T LEFT JOIN TT
ON T.Computed = TT.ReferenceComputedColumn;
See how it's working.
See also this article Properly Persisted Computed Columns by Paul White.
Try this
SELECT CONVERT(NVARCHAR(255), #AgentCode)
SELECT CAST([PictureId] AS NVARCHAR(4)) From Category

How can I ignore default value on SQL insert statement?

I've already set default value for some of my columns.
CREATE TABLE [dbo].[TEST]
(
[id] [INT] NULL,
[fname] [VARCHAR](50) NULL,
[lname] [VARCHAR](50) NULL,
[default1] [VARCHAR](50) NULL,
[default2] [VARCHAR](50) NULL,
[default3] [VARCHAR](50) NULL
) ON [PRIMARY]
ALTER TABLE [dbo].[TEST]
ADD CONSTRAINT [DF_TEST_job] DEFAULT ('test1') FOR [default1]
ALTER TABLE [dbo].[TEST]
ADD CONSTRAINT [DF_TEST_default2] DEFAULT ('test2') FOR [default2]
ALTER TABLE [dbo].[TEST]
ADD CONSTRAINT [DF_TEST_default3] DEFAULT ('test3') FOR [default3]
Now I'm going to set all columns with default values to null in my INSERT statement sometimes.
I know that if I provide values for the columns in the INSERT, their defaults will be ignored. But I'm looking for a way to set default values off on some inserts.
I know that it might be impossible, but I want to learn it's way (if there is.
I don't fully understand what you're trying to ask here....
If you provide a value for a column - even if it's NULL, in your INSERT statement, then SQL Server will use that provided value and skip any default value defined on the column.
So by just providing NULL, you're basically doing what your title asks: ignore the default value of the column.... the default value of a column is only used if you omit that column entirely from your INSERT statement....

Audit Trail Trigger generation

Working on Audit Trail system and decided to do it with Shadow/History table with triggers.
Followed this Audit Trail Article and trying to use CodeSmith Generator tool
I dont understand how it creates the history table and the trigger.
Is any one could understand how it works and help me on it.
I tried google to understand it. But there is no clear example
Nothing is clear with the below to me
Audit Table looks like this
CREATE TABLE [dbo].[<%= AuditTableName %>] (
[ChangeLogID] [int] IDENTITY (1, 1) ,
[OperationType] [varchar] (10) NOT NULL ,
[ChangeTimestamp] [datetime] NOT NULL ,
[MadeBy] [varchar] (6) NOT NULL ,
[TableChanged] [varchar] (50) NOT NULL
) ON [PRIMARY]
Detail Table looks like this
CREATE TABLE [dbo].[<%= AuditFieldTableName %>] (
[FieldName] [varchar] (50) NOT NULL ,
[ChangeLogID] [int] NOT NULL ,
[BeforeValue] [sql_variant] NOT NULL ,
[AfterValue] [sql_variant] NOT NULL
) ON [PRIMARY]
How to generate this and add trigger and how can i insert AuditFieldTableName values?
As we have different types of columns in multiple tables, the audit table that you have specified wouldn't really suffice the cause. I suggest the following audit table:
TABLE auditEntry (
auditEntryId INTEGER PRIMARY KEY,
operationType VARCHAR(10) NOT NULL, -- For INSERT / UPDATE / DELETE
changeTimestamp DATETIME NOT NULL,
madeBy VARCHAR(50) NOT NULL,
tableName VARCHAR(30) not null, -- stores the name of the table changed
columnName VARCHAR(30) not null, -- stores the name of column changed
oldInt INTEGER,
newInt INTEGER,
oldVarchar VARCHAR(100),
newVarchar VARCHAR(100),
oldDate DATETIME,
newDate DATETIME)
Now I think it's a cakewalk for you to write row level triggers for INSERT, UPDATE and DELETE on your tables, if you have working knowledge of writing them. Search MSDN on how to write such triggers and you will be fine.