1

I need to enter primary key in table as in below format

YYYY/MMM/NNNNNN

Where, YYYY is the current year, MMM is Month , and NNNNNN is a sequence no from 000001, 000002, 000003, .... 999999.

So my primary key will look like 2012/Oct/000001 or 2012/Oct/000010 ....

How can I generate this type of code..

I can get Year and Month from Getdate() function. But how can I manage sequence number on every insert. can you please give me logic for that?

8
  • 2
    Which DB are you using? Mysql, orcale, sqlite, ...? Commented Oct 30, 2012 at 9:41
  • I am wondering why do you want this :o Commented Oct 30, 2012 at 9:45
  • @OlafDietsche I am using MSSql.. Commented Oct 30, 2012 at 9:46
  • 1
    @OlafDietsche getdate is definitely not mysql. T-SQL, I think. Commented Oct 30, 2012 at 9:46
  • 1
    @OlafDietsche I didn't read nawfal's question as a question to you, but to the OP. Commented Oct 30, 2012 at 9:49

4 Answers 4

4

By far the easiest way would be to let SQL Server handle the dishing out of consecutive numbers using an INT IDENTITY column - and then use a trigger to create that specific format that you need, in a separate column.

So given this table:

CREATE TABLE SampleTable 
             (ID INT IDENTITY, SaleDate DATE, ComputedPK VARCHAR(25) )

you could use a trigger like this to compute the ComputedPK from the ID (autonumber, handled by SQL Server) and the SaleDate as the date column:

CREATE TRIGGER trgSampleTableInsert
ON dbo.SampleTable FOR INSERT
AS 
    UPDATE dbo.SampleTable
    SET ComputedPK = CAST(YEAR(i.SaleDate) AS CHAR(4)) + '/' + DATENAME(MONTH, i.SaleDate) + '/' + RIGHT('000000' + CAST(i.ID AS VARCHAR(6)), 6) 
    FROM dbo.SampleTable s
    INNER JOIN INSERTED i ON s.ID = i.ID

This approach will not start at 1 for each month, however - but do you really need that? Isn't a sequential number (even across months) good enough?

Update: of course, if you're using SQL Server 2012 (you didn't specify which version of SQL Server you're using...) - you could use a SEQUENCE object to handle the consecutive numbering - and you could even reset that sequence to 1 again every start of a month ....

Sign up to request clarification or add additional context in comments.

6 Comments

Once you've decided to compute it, and the computation is entirely based (as here) on other columns in the same row, any reason you'd prefer to use a trigger here rather than a computed column?
I was about to ask exactly the same thing. ComputedPK AS CAST(YEAR(SaleDate) AS CHAR(4)) + '/' + DATENAME(MONTH, SaleDate) + '/' + RIGHT('000000' + CAST(ID AS VARCHAR(6)), 6). It can even be marked as persisted, so that it is stored as were it a regular modifiable field.
@Damien_The_Unbeliever: since I cannot persist the computed column (due to the non-deterministic nature of the formula), I felt it was more efficient to compute it in a trigger and store it - rather than having it computed every time you access the column
@hvd: actually, I cannot make it PERSISTED: Msg 4936, Level 16, State 1, Line 1 - Computed column 'ComputedPK' in table 'SampleTable' cannot be persisted because the column is non-deterministic. - the culprit is the DATENAME function - it's not considered deterministic...
@marc_s Oops, that's right, that isn't deterministic, because the month names depend on other data than what's in the table. It should work with a slight modification, but I'll test it first.
|
1
SELECT 
CONCAT(
      DATEPART(YEAR, GETDATE()),
      '/',
      DATENAME(MONTH,GETDATE()),
      '/',
      REPLACE(STR(((SELECT COUNT(*) FROM yourtable WHERE monthname = DATENAME(MONTH,GETDATE()) GROUP BY monthname) + 1),6,0),' ','0')
  )
  )

This is untested now tested. You would have to add a monthname column (there is a way of doing this without adding a column, but this is the most convenient)

You can also cast and use addition if you don't want to rely on concat. http://sqlfiddle.com/#!6/3e43d/6

2 Comments

This will work IF he's using SQL Server 2012 (only - CONCAT is a new feature in the 2012 version)
@marc_s It might not work even then, haven't tested this at all.
0

Why don't you just consider a compound key with an identity/numeric column and a date column (or if the day is not needed, the year/month)?

This would give you the same behaviour and would probably be a bit simpler to implement/maintain

I still would like to know the reasoning behind this - just so we can make a better educated guess

Comments

0

Set your Primary Key on two columns. One of them will represent the Daten and the other one the Serial number. Set a Sequence on the Serial column which increases automatically. This will make it easier for you filter the Date part of the Key.

3 Comments

That doesn't cover him when he switches months, though.
I'm assuming the sequence should be per month, so after all the entries for October, you'd get 2012/Nov/000001. Your solution won't do this.
The OP didnt mention this should be the case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.