I have this table "ART":
COD - varchar(20) PK
DES - varchar(50)
Simple example data are:
COD DES
MM000000 AA
MM000001 BB
MM000010 CC
MM000145 DD
How do I increment the column COD by 1 every insert? The final pk format must be: 'MM' + 6 digits
DECLARE #a INT = 0;
WHILE #a < 100
BEGIN
SELECT 'MM' + RIGHT('000000' + CAST(#A as VARCHAR(6)),6)
SET #a += 1
END
CREATE TABLE #a
(
Id INT IDENTITY(1,1),
Code AS 'MM' + RIGHT('000000' + CAST(Id as VARCHAR(255)),6)
)
INSERT INTO #a DEFAULT VALUES
INSERT INTO #a DEFAULT VALUES
INSERT INTO #a DEFAULT VALUES
SELECt * FROM #a
but identity can be an unevenly growing value
I guess it is better and more safe to define the identity column as a computed column in the table definition
Please refer to SQL tutorial on Custom Sequence String as SQL Identity Column
The solution requires a simple identity column of integer data type increasing by 1 with every insert
Then a second column, actually a computed column created as follows will help you for the solution of your requirement
COD as dbo.udf_ZeroPaddingAndConcat('ID-', CAST(Id as nvarchar(10)),6,'0'),
Actually the custom function module is just doing the zero padding here as
SELECT #Prefix + RIGHT(REPLICATE(#PaddingChar, #Length) + CAST(#Id as nvarchar(10)), #Length)
You will also find the function source code in the same referenced document
Related
I will try to demonstrate what I am trying to achieve. This is an oversimplified example for my case.
Suppose I have a table contains two columns
ID YEAR
--- ----
1 2017
2 2018
and I have a search term 2017 / 1
What I want to do is something like this
select * from table where 'YEAR / ID' LIKE '%searchterm%'
Is this possible ?
Thanks in advance.
In my opinion the most effective way is:
Firstly divide String x = "2017 / 1" to two int values int year = 2017, int id = 1. I don't know what kind of programing language you are using but all of programing languages have special functions to make it easily (between all values you have '/').
Then use this query:
Select *
from table
where year = 2017
and id = 1
Use Below query, I have considered your search text format as 2017 / 1.
DECLARE #tblTest AS Table
(
Id INT,
YearNo INT
)
INSERT INTO #tblTest values (1,2017)
INSERT INTO #tblTest values (2,2018)
INSERT INTO #tblTest values (3,2017)
INSERT INTO #tblTest values (4,2018)
DECLARE #searchterm VARCHAR(50)='2017 / 1'
LEFT will give you string starting from left position to applied length.
RIGHT will give you string starting from right position to applied length
SELECT
*
FROM #tblTest
WHERE YearNo=LEFT(#searchterm,4)
AND Id = REPLACE(RIGHT(#searchterm,LEN(#searchterm)-(CHARINDEX('/',(REPLACE(#searchterm, ' ', ''))))),'/','')
If your database compatibility could be 130 then You can Try String_Split ref https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql
Sql most long awaited function (as msdn says)
Declare #tbl table (id int Identity(1,1), value nvarchar(5))
Insert into #tbl ([value]) SELECT value from STRING_SPLIT(#searchstring,'/')
Declare #id int
Select #id = cast(value as int) from #tbl where id=2 --will give 1
Declare #value int
Select #id = cast(value as int) from #tbl where id=1 --ill give 2017
-- —now use them in sql
select * from table where YEAR=#value and ID = #id
You are going to screw up the performance if you do anything like below
select * from table where 'YEAR / ID' LIKE '%searchterm%'
Best way is you can split your search and supply to respective col
Declare #Search varchar(15)='2017/1'
Declare #Year int = (select LEFT(#Search,CHARINDEX('/',#search)-1))
Declare #month int = (select Right(#Search,(len(#search) -CHARINDEX('/',#search))))
select * from #temp where id=#month and year=#Year
Try this code :
select * from table where YEAR + ' / ' + ID LIKE '%searchterm%'
this query will run, but it will perform very poor.
Consider the table in SQL Server 2012
789-0000000
The above number will be consider as a string in SQL Server 2012, but whenever I update the record I need increment to 1.
For example:
When I update the record 1 it should increment to 789-0000001
When I update the record 2 it should increment to 789-0000002
Finally increment should done only 789-0000000
The best solution is to use
an ID INT IDENTITY(1,1) column to get SQL Server to handle the automatic increment of your numeric value
a computed, persisted column to convert that numeric value to the value you need
So try this:
CREATE TABLE dbo.YourTable
(ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
CompanyID AS '789-' + RIGHT('000000' + CAST(ID AS VARCHAR(7)), 7) PERSISTED,
.... your other columns here....
)
Now, every time you insert a row into dbo.YourTable without specifying values for ID or CompanyID:
INSERT INTO dbo.YourTable(Col1, Col2, ..., ColN)
VALUES (Val1, Val2, ....., ValN)
then SQL Server will automatically and safely increase your ID value, and CompanyID will contain values like 789-0000001, 789-0000002,...... and so on - automatically, safely, reliably, no duplicates.
DECLARE #base int = 0
UPDATE TableX
SET
TableX.Value = 'Prefix' + RIGHT('0000000' + CAST(#base AS nvarchar),7),
#base = #base + 1
FROM
TableX
you can split the string
e.g.:
SELECT Item
FROM dbo.SplitString('Apple,Mango,Banana,Guava', ',')
then cast it
e.g.:
SELECT CAST(YourVarcharCol AS INT) FROM Table
then manually increment it
e.g.:
DECLARE max_id INT
SET #max_id = (SELECT MAX(id) FROM source_table)
DECLARE cursor_name CURSOR FOR
SELECT columns, to, copy
FROM source_table
OPEN cursor_name
FETCH NEXT FROM cursor_name
INTO #columns, #to, #cop
at update
e.g.:
declare #i int = SELECT ISNULL(MAX(interfaceID),0) + 1 FROM prices
update prices
set interfaceID = #i , #i = #i + 1
where interfaceID is null
you can understand how complicate this is and why
the solution using a constant to store that prefix is right one.
Declare #str varchar(max) = '789-0000000'
Select
SUBSTRING ( #str ,0 ,CHARINDEX ( '-' ,#str ))
+'-'
+
(SUBSTRING ( #str ,(CHARINDEX ( '-' ,#str)+1) ,(7-LEN(CAST(SUBSTRING ( #str ,CHARINDEX ( '-' ,#str)+1,LEN(#str)) as int))
)
)+
CAST(CAST(SUBSTRING ( #str ,CHARINDEX ( '-' ,#str)+1,LEN(#str)) as int)+1 as varchar))
When #str='789-0001947'
Output #str= 789-0001948
You can write a update trigger on the table with above logic.
I want to generate a pattern in SQL Server.
e.g. PA0001
and increment it every time (meaning if PA0001 has already been generated the next should be PA0002 and so on).
I have no idea how to go about this!
Can anyone help?
The canonical way is to have an indentity column and then create this code as a computed column:
create table . . . (
inc int not null identity(1, 1),
. . .
code as ('PA' + right('0000' + cast(inc as varchar(255)), 4)
This only works with one prefix -- if you want all values to start with 0001. If you have multiple prefixes, you can:
Use a trigger.
Calculate the code in queries.
Change your requirements so you can use codes that do not have other meanings.
You can write as:
create table Test
(
ID int identity not null primary key,
pattern varchar(100)
)
Go
create function Nextpattern (#id int)
returns varchar(20)
as
begin
return 'PA' +
CONVERT(VARCHAR(10), GETDATE(), 110) + right('00' + convert(varchar(10), #id), 2)
end
--Solution 1:
Go
alter table Test add Newpattern as dbo.Nextpattern(ID)
Go
insert into Test values (1)
Go
--solution2:
-- not good as what if two processes attempt to
-- add a row to the table at the exact same time?
create function dbo.fnNextpattern()
returns varchar(20)
as
begin
declare #lastval varchar(20)
set #lastval = (select max(pattern) from Test)
if #lastval is null set #lastval = 'PA' +
CONVERT(VARCHAR(10), GETDATE(), 110) + '01'
declare #i int
set #i = right(#lastval,2) + 1
return 'PA' +
CONVERT(VARCHAR(10), GETDATE(), 110)+ right('00' + convert(varchar(10),#i),2)
end
go
DEMO
I have table in my SQL Server database with following columns
ID | NAME | DOB | APPLICATION NO |
1 | JOHN | 31/05/1986 | KPL\2014\1 |
2 | MARY | 26/04/1965 | KPL\2014\2 |
3 | VARUN | 15/03/1972 | KPL\2014\3 |
Here column ID is an auto increment column and column APPLICATION NO is dependent on ID.
That means APPLICATION NO is the concatenation of KPL\, YEAR and column value of ID.
Then how can I make an insert query?
Why don't you use a computed column ?
I would change the table's definition.
add a "year" column
add an "application_name" column (if it's not always "KPL").
then create your computed column, with the needed fields
alter table <yourTable> add computed_application_name as (application_name + '/' + CAST(<yearColumn> as VARCHAR(4) + '/' + <otherColumn> + CAST(id as VARCHAR(MAX))
Just use a computed column:
alter table t
add application_no as ('KPL' + cast(year(getdate()) as varchar(255)) + cast(id as varchar(255));
It occurs to me that you really want the year when the row was inserted. For that purpose, I would recommend adding a createdat column and then using that instead of getdate():
alter table t add CreatedAt datetime default getdate();
If you have data in the table, then set the value (this is not needed if the table is empty):
update table t set CreatedAt = getdate();
Then define application_no:
alter table t
add application_no as ('KPL' + cast(year(CreatedAt) as varchar(255)) + cast(id as varchar(255));
Simply use a computed column for 'APPLICATION_NO':
create table tbl (
ID int,
NAME varchar(10),
DOB date,
APPLICATION_NO as ('KPL\'+cast(year(dob) as char(4))+'\'+cast(id as varchar))
)
You can further persist and index it as well.
You can create a trigger to run after insert. In your insert, ignore application_no. And your trigger update this column based on ID.
Something like this:
CREATE TRIGGER [TRIGGER_TABLE1] ON TABLE1
AFTER INSERT
AS
BEGIN
UPDATE TABLE1
SET APPLICATION_NO = 'KPL\' + CONVERT(VARCHAR, YEAR(GETDATE())) + '\' + CONVERT(VARCHAR, ID)
WHERE APPLICATION_NO IS NULL
END
EDIT: This way, you should be able to use other columns values as well. APPLICATION_NO just need to accept NULL values. So you control like this what will be updated or not.
Use SCOPE_IDENTITY get the inserted record Id
Declare #Id INT
Insert Into TABLENAME(NAME ,DOB )
Values('Name','1/1/1990')
Set #Id=SCOPE_IDENTITY()
IF(#Id>0)
begin
declare #col varchar(100)=''
set #col= 'KPL\' + CONVERT(varchar(4),YEAR(GETDATE()))+'\' + CONVERT(varchar(4),#Id)
Update TABLENAME
SET APPLICATIONNO= #col
Where ID = #id
end
If you really want to do it by yourself with an insert statement:
assuming that you want to insert data from another table
and TABLE1 is the table you described in your question and TABLE2 would be the table you want to import data from:
DECLARE #MAXID INT
SELECT #MAXID = MAX(ID) FROM TABLE1
INSERT INTO TABLE1
(NAME,DOB,APPLICATION_NO)
SELECT
NAME,
DOB,
'KPL\'
+ CONVERT(CHAR(4),YEAR(GETDATE()) +'\'
+ CONVERT(VARCHAR(25), #MAXID + ROW_NUMBER() OVER (ORDER BY NAME)) AS APPLICATION_NO
FROM TABLE2
I have a table cell of type nvarchar(max) that typically looks like this:
A03 B32 Y660 P02
e.g. a letter followed by a number, separated by spaces. What I want to do is get a sum of all those numbers in a SQL procedure. Something rather simple in other languages, but I am fairly new to SQL and besides it seems to me like a rather clumsy language to play around with strings.
Aaanyway, I imagine it would go like this:
1) Create a temporary table and fill it using a split function
2) Strip the first character of every cell
3) Convert the data to int
4) Update target table.column set to sum of said temporary table.
So I got as far as this:
CREATE PROCEDURE [dbo].[SumCell] #delimited nvarchar(max), #row int
AS
BEGIN
declare #t table(data nvarchar(max))
declare #xml xml
set #xml = N'<root><r>' + replace(#delimited,' ','</r><r>') + '</r></root>'
insert into #t(data)
select
r.value('.','varchar(5)') as item
from #xml.nodes('//root/r') as records(r)
UPDATE TargetTable
SET TargetCell = SUM(#t.data) WHERE id = #row
END
Obviously, the first char stripping and conversion to int part is missing and on top of that, I get a "must declare the scalar variable #t" error...
Question is not very clear so assuming your text is in a single cell like A3 B32 Y660 P20 following snippet can be used to get the sum.
DECLARE #Cell NVARCHAR(400), #Sum INT, #CharIndex INT
SELECT #Cell = 'A3 B32 Y660 P20',#Sum=0
WHILE (LEN(LTRIM(#Cell))>0)
BEGIN
SELECT #CharIndex = CHARINDEX(' ',#Cell,0)
SELECT #Sum = #Sum +
SUBSTRING(#Cell,2,CASE WHEN #CharIndex>2 THEN #CharIndex-2 ELSE LEN(#Cell)-1 END )
SELECT #Cell = SUBSTRING(#Cell,#CharIndex+1,LEN(#Cell))
IF NOT (#CharIndex >0) BREAK;
END
--#Sum has the total of cell numbers
SELECT #Sum
I'm making the assumption that you really want to be able to find the sum of values in your delimited list for a full selection of a table. Therefore, I believe the most complicated part of your question is to split the values. The method I tend to use requires a numbers table, So I'll start with that:
--If you really want to use a temporary numbers table don't use this method!
create table #numbers(
Number int identity(1,1) primary key
)
declare #counter int
set #counter = 1
while #counter<=10000
begin
insert into #numbers default values
set #counter = #counter + 1
end
I'll also create some test data
create table #data(
id int identity(1,1),
cell nvarchar(max)
)
insert into #data(cell) values('A03 B32 Y660 P02')
insert into #data(cell) values('Y72 A12 P220 B42')
Then, I'd put the split functionality into a CTE to keep things clean:
;with split as (
select d.id,
[valOrder] = row_number() over(partition by d.cell order by n.Number),
[fullVal] = substring(d.cell, n.Number, charindex(' ',d.cell+' ',n.Number) - n.Number),
[char] = substring(d.cell, n.Number, 1),
[numStr] = substring(d.cell, n.Number+1, charindex(' ',d.cell+' ',n.Number) - n.Number)
from #data d
join #numbers n on substring(' '+d.cell, n.Number, 1) = ' '
where n.Number <= len(d.cell)+1
)
select id, sum(cast(numStr as int))
from split
group by id