Automatically generate unique id like UID 22-001 - sql

I want to automatically generate unique id with per-defined code attach to it.
ex:
'UID 22-001..
'UID 22-002..
'UID 22-003 ('22' is year 2022)
and then when the year is 2023 it will be generated as;
'UID 23-001..
'UID 23-002..
'UID 23-003..
and so on. Thanks in advance for the help.

Consider you have table with this columns:
id varchar(max),
name varchar(20),
address varchar(20))
You are going to insert value with the ID format that you mentionned.
Here is an example query:
INSERT INTO TABLE_NAME
VALUES(
(SELECT concat('UID ' , (SELECT RIGHT(YEAR(getdate()),2)),'-',(select RIGHT('000'+(CAST(MAX(CAST(RIGHT(ID,2) AS INT) + 1) AS NVARCHAR )),3) FROM TABLE_NAME))),'RAM','INDIA')

Related

create table using select statement in place of table_name

create table using select statement in place of table_name.
I want to create a table with the name B100 where '100' is the maximum value of id in table 'A'
example:
table A:
id name
100 harsh
78 Vishal
23 Ivan
34 Hardik
need to create table with name 'B{max_value_of_id_in_A}'.
the fields in table B is the same (id, name);
what I try:
create table CONCAT('B', (Select max(id) from A))
(
id int,
name varchar(50)
)
To do this, you need to use dynamic sql. A quick and dirty example is:
create table test(id smallint, name varchar(15));
insert test (id, name) values
(98, 'harsh'), (78, 'Vishal'), (23, 'Ivan'), (34, 'Hardik');
declare #sql nvarchar(200);
set #sql = N'create table B' + format((select max(id) from test), 'D3')
+ N'(
id int,
name varchar(50)
);'
select #sql;
exec(#sql);
exec('select * from B098');
Notice that I had to resort to dynamic sql to actually use that table within the same batch. As the others have suggested, you should reconsider the path you have chosen for many reasons. Perhaps foremost is that this requires a rather advanced level of skill - you will likely need much help to make use of your table. You should consult with your DBA to get their opinion (and permission).

Generating name based on ID and current year using SQL Server

I am trying to generate value for the ProjektNummer (Name) column based on the value of the ID (primary key column.
So for example, when ID is 142, then the ProjektNummer should be 19142. 19 indicating the current year and 142 is the value of its ID.
Now, when the year changes, the id part in the value of the project name column needs to be restarted from zero while the actual ID should follow the identity and be incremented by 1 as usual.
So if the last record in the Year 2019 has ID=164, the first record in the year 2020 should be:
ID: 165 ProjektNummer: 20001
.. and the second record in year 2020 would be:
ID: 166 ProjektNummer: 20002
One way to achieve this is by creating a new view say 'vMaxLastId' and storing the max value of 'ID' for its corresponding year. This record will be used as a reference in another trigger.
So, if the first record in the year 2020 has ID: 165 Another trigger will subtract the value (164) for year 2019 (which is stored in the view), from the value of 'ID' after inserting a new record in 'table1' using the second trigger. (this should be done before inserting tho)
165-164=1
166-164=2
167-164=3
....
When the year will change from 2019 to 2020 the max id and year in 2020 will be added as a new record in the view. I have implemented this but there are multiple problems associated with this approach.
Kindly suggest me any possible way to solve this problem. I am willing to make any kind of change to the DB, query or trigger or the whole concept.
The first thought that crossed my mind would be to create a SEQUENCE object to generate the ID portion of the value. Since there are no fancy rules around the numbering, just this should do.
CREATE SEQUENCE dbo.ProjektID;
That will give you a bigint. To consume it, CONCAT that to the current year, and put your padding zeros onto the sequence value. You could set this as the default value for the column.
CONCAT( YEAR( GETDATE() ) % 100 , RIGHT( CONCAT('000', NEXT VALUE FOR dbo.ProjektID), 3))
Then schedule a job to run at midnight on the first of the year to restart the sequence.
ALTER SEQUENCE dbo.ProjektID
RESTART;
I think that would cover your requirements.
The most pragmatic solution I could think of is the use of a INSTEAD OF trigger on that specific main table.
My test table:
CREATE TABLE dbo.MyTestProject
(
id INT IDENTITY(1, 1) NOT NULL PRIMARY KEY
, dateInserted DATETIME2(7) NOT NULL
, projectNumber INT NULL
);
And the example trigger:
CREATE TRIGGER dbo.triMyTestProject
ON dbo.MyTestProject
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE
#maxYear INT
, #maxNumber INT
, #startNumber INT
, #dateInserted DATETIME2;
SELECT
#dateInserted = dateInserted
FROM Inserted;
SET #startNumber = CAST(FORMAT(#dateInserted, 'yy') AS INT) * 1000 + 1;
SELECT
#maxNumber = MAX(projectNumber)
, #maxYear = ISNULL(MAX(YEAR(dateInserted)), YEAR(#dateInserted))
FROM dbo.MyTestProject;
INSERT INTO dbo.MyTestProject
(
dateInserted
, projectNumber
)
VALUES
(
#dateInserted, IIF(YEAR(#dateInserted) > #maxYear OR #maxNumber IS NULL, #startNumber, #maxNumber + 1)
);
END;
Add test data:
INSERT INTO dbo.MyTestProject (dateInserted) VALUES (SYSDATETIME());
INSERT INTO dbo.MyTestProject (dateInserted) VALUES (SYSDATETIME());
INSERT INTO dbo.MyTestProject (dateInserted) VALUES (SYSDATETIME());
INSERT INTO dbo.MyTestProject (dateInserted) VALUES ('20200102');
INSERT INTO dbo.MyTestProject (dateInserted) VALUES ('20200202');
Test result:
SELECT * FROM dbo.MyTestProject;
id dateInserted projectNumber
----------- --------------------------- -------------
1 2019-12-06 17:27:58.8813628 19001
2 2019-12-06 17:27:58.8833638 19002
3 2019-12-06 17:27:58.8883448 19003
4 2020-01-02 00:00:00.0000000 20001
5 2020-02-02 00:00:00.0000000 20002

How to create custom, dynamic string sequence in SQL Server

Is there any way to dynamically build sequences containing dates/strings/numbers in SQL Server?
In my application, I want every order to have a unique identificator that is a sequence of: Type of order, Year, Month, Incrementing number
(ex: NO/2016/10/001, NO/2016/10/002)
where NO = "Normal order", 2016 is a year, 10 is a month and 001 is an incrementing number. The idea is that it is easier for employees to comunicate using these types of identificators (of course this sequence would not be primary key of database table)
I know that I could create a stored procedure that would take Order type as an argument and return the sequence, but I'm curious if there is any better way to do it.
Cheers!
An IDENTITY column might have gaps. Just imagine an insert which is rollbacked out of any reason...
You could use ROW_NUMBER() OVER(PARTITION BY CONVERT(VARCHAR(6),OrderDate,112) ORDER BY OrderDate) in order to start a sorted numbering starting with 1 for each month. What will be best is depending on the following question: Are there parallel insert operations?
As this order name should be unique, you might run into unique-key-violations where you'd need complex mechanisms to work around...
If it is possible for you to use the existing ID you might use a scalar function together with a computed column (might be declared persistant):
CREATE TABLE OrderType(ID INT,Name VARCHAR(100),Abbr VARCHAR(2));
INSERT INTO OrderType VALUES(1,'Normal Order','NO')
,(2,'Special Order','SO');
GO
CREATE FUNCTION dbo.OrderCaption(#OrderTypeID INT,#OrderDate DATETIME,#OrderID INT)
RETURNS VARCHAR(100)
AS
BEGIN
RETURN ISNULL((SELECT Abbr FROM OrderType WHERE ID=#OrderTypeID),'#NA')
+ '/' + CAST(YEAR(#OrderDate) AS VARCHAR(4))
+ '/' + REPLACE(STR(MONTH(#OrderDate),2),' ','0')
+ '/' + REPLACE(STR(#OrderID,5),' ','0')
END
GO
CREATE TABLE YourOrder
(
ID INT IDENTITY
,OrderDate DATETIME DEFAULT(GETDATE())
,OrderTypeID INT NOT NULL --foreign key...
,Caption AS dbo.OrderCaption(OrderTypeID,OrderDate,ID)
);
GO
INSERT INTO YourOrder(OrderDate,OrderTypeID)
VALUES({ts'2016-01-01 23:23:00'},1)
,({ts'2016-02-02 12:12:00'},2)
,(GETDATE(),1);
GO
SELECT * FROM YourOrder
The result
ID OrderDate OrderTypeID Caption
1 2016-01-01 23:23:00.000 1 NO/2016/01/00001
2 2016-02-02 12:12:00.000 2 SO/2016/02/00002
3 2016-10-23 23:16:23.990 1 NO/2016/10/00003
You could create a computed column in your table definition which concatenates other values in your database into the kind of Identifier you're looking for.
Try this for a simplified example:-
CREATE TABLE Things (
[Type of Order] varchar(10),
[Year] int,
[Month] int,
[Inc Number] int identity(1,1),
[Identifier] as [Type of Order] + '/' + cast([Year] as varchar) + '/' + cast([Month] as varchar) + '/' + cast([Inc Number] as varchar)
)
insert into Things
values
('NO',2016,10)
select * from Things
If you wanted to do something more complex you could always use a trigger to update the column post insert or update.

Custom ID column based on year and month

I have the below create table code:
CTranID int identity(1,1) constraint pk_CTrainID Primary Key,
CustomerID AS 'PB' +
cast(datepart(yy,getdate()) as varchar(25)) +
cast(datepart(mm,getdate()) as varchar(25)) +
RIGHT('000000000' + CAST(CTranID AS VARCHAR(10)), 9),
What is happening is that when the record inserts it goes as per current year and month.
But as a testing I changed the system month and when I query in T-SQL, I see the previously inserted records as for the changed month.
Where in case it should have been for the month before changing the system month.
You are using a computed column. Every time you query that table the value of the column, for each row, will be calculated on the fly. That is why you are seeing changing values as you change the system clock.
Instead, store the date of creation in a column and base your calculated column on that column:
CREATE TABLE peter (
CTranID int identity(1,1) constraint pk_CTrainID Primary Key,
CreatedOn DateTime2 DEFAULT (SYSDATETIME()) NOT NULL, -- New Column
CustomerID AS 'PB' + cast(datepart(yy,CreatedOn) as varchar(25)) + cast(datepart(mm,CreatedOn) as varchar(25)) + RIGHT('000000000' + CAST(CTranID AS VARCHAR(10)), 9)
)
INSERT INTO peter
DEFAULT values
SELECT * FROM peter
CTranID CreatedOn CustomerID
1 2015-05-26 PB20155000000001
The whole point of a computed column is that it gets computed every time it is accessed - if the underlying components of the computation change, so will the columns value, .
You will need to change your CustomerId column to a normal, persisted column and find another way to auto-populate it.
CREATE TABLE...
CustomerID VARCHAR(50), -- i.e. not computed
Ideally, this will be done by the app inserting the row, but you could I guess also resort to a trigger, e.g.
CREATE TRIGGER T_Customer ON CUSTOMER AFTER INSERT
AS
BEGIN
UPDATE c
SET c.CustomerID = 'PB' + cast(datepart(yy,getdate()) as varchar(25)) +
cast(datepart(mm,getdate()) as varchar(25)) +
RIGHT('000000000' + CAST(ins.CTranID AS VARCHAR(10)), 9)
FROM Customer c
INNER JOIN Inserted ins on c.CTranID = ins.CTranID;
END;
GO
SqlFiddle here

Add $ symbol to column values

I want to add $ symbol to column values and convert the column values to western number system
Dollars
4255
25454
467834
Expected Output:
$ 4,255
$ 25,454
$ 467,834
My Query:
select ID, MAX(Date) Date, SUM(Dollars) Dollars, MAX(Funded) Funding from Application
Dollars is the int datatype and needs to be changed.
You can do something like that. Converting from money to varchar with style 1 adds thousand separator:
declare #value int = 4255
select '$ ' + replace(convert(varchar(100), convert(money, #value), 1), '.00', '')
-- output: $ 4,255
If you process the data from SQL Server in any application, formatting is much easier to do in the code though.
Hello basing on your output you can approach like this also
declare #table Table (ID INT)
INSERT INTO #table (ID) VALUES (4255)
INSERT INTO #table (ID) VALUES (25454)
INSERT INTO #table (ID) VALUES (467834)
SELECT '$' + LEFT(CONVERT(VARCHAR(100),CAST(id AS MONEY),1),LEN(id)+ 1) from #table
Thanks