non-identity column auto increment - sql

I'm working on a project to consolidate data (from 2 different DBs). I have created a table that contains a few columns:
MAPPING_ID int
ContentID int
ContentValue varchar(200)
For Example, when I do my 1st set of inserts against the original data source everything is good.
Mapping_ID: 53
ContentID: 53
ContentValue: Original Data 1
Mapping_ID: 54
ContentID: 54
ContentValue: Original Data 2
But when I do my second set of inserts against the another source (the data I'm trying to merge) I would like the Mapping_ID column to continue to the next number (i.e. 55,56,57...)
I looked at the row_number function but that starts at 1. Is there a way to start it at 55?
I suppose I could make that Mapping_ID column an Identity field, but turn it off during the first insert and then seed it with the max value (54) and then turn it on during the second insert.
Is there another way to accomplish this?

In SQL Server 2012+, you may use SEQUENCE objects to populate non-identity columns with autoincrement values. Plus you may use same SEQUENCE for different tables to make numeration pass-through and obtain values from sequences in SELECT and UPDATE queries.
First, create SEQUENCE:
CREATE SEQUENCE SchemaName.SequenceName
START WITH 1
INCREMENT BY 1 ;
Then, create DEFAULT constraint with values from sequence on required column:
ALTER TABLE tableName ADD CONSTRAINT constraint_unique_name DEFAULT NEXT VALUE FOR SchemaName.SequenceName FOR Mapping_ID;

There's actually a brand new way to do this kind of thing as of SQL Server 2012: the sequence object. I'm sorry I can't script out a procedure for you as I'm working in the MySQL world at present, but it's super easy to implement. The basic idea is you're maintaining a separate database object with its own seed and increment amount, but there are some caveats to bear in mind regarding their difference from traditional identity values (e.g. you can overwrite them), so make sure you do some research.
Here are a couple of articles to get you started. If you have trouble, hit me back and I'll try to work through the code with you.
https://msdn.microsoft.com/en-us/library/ff878091.aspx
https://msdn.microsoft.com/en-us/library/ff878370.aspx
Good luck!

To get row_number() to start at 55, you could just add 54 (or whatever number) to your row_number() calculation:
(row_number() over (partition by Y order by X)) + 54

Related

Adding a computed column that uses MAX

I need to create a sequential number column for record number proposes
I am OK with losing sequence if I delete a row from the middle of the table
For example
1
2
3
If I delete 2, I am ok with new column been 4.
I tried to alter my table to
alter table [dbo].[mytable]
add [record_seq] as (MAX(record_seq) + 1)
but I am getting An aggregate may not appear in a computed column expression or check constraint.
Which is a bit confusing? do I need to specify an initial value? is there a better way?
If you're looking to allocate a sequence number even in cases where the table doesn't get a record inserted, I would handle it in the process responsible for performing those inserts. Create another table, in this table keep track of the max identity value of that sequence. Each time you want to perform an insert, reserve the sequence number you want by updating that table first. If you rely on selecting the max existing value, you could be at risk of multiple sessions getting the same "new" sequence number before inserting. Even if the insert fails, you will have incremented that control table so nothing else uses that value that has been reserved.
Its not supported in MsSql. You can use identity column:
ALTER TABLE [dbo].[mytable]
ADD [record_seq] INT IDENTITY
Or use trigger to update your seq column after insert and/or delete

Filling incremental unqiue values for a newly created PK

I currently have a table with many rows, but no PK at all. I now require to have a unique, non-null, > 0 PK for every row.
I'm created the column for PK, but how I can I quickly fill in the column with an incremental value starting from 1?
Any method, a single SQL line, or a SQL line to be executed as many times as are rows are good enough for me.
Something like
update sometable set newkeyfield = Row_Number() Over();
should do not a DB2 bloke, but should be close.
Try using a DB2 Sequence object. They are designed for creating unique sequences of numbers. Pick your data type.
CREATE SEQUENCE mySeq as int;
You retrieve and increment the sequence in one step, using a sequence reference
NEXT VALUE FOR mySeq
You expression can use this in an INSERT, UPDATE, or MERGE, or most places you can use an expression.

How are these tasks done in SQL?

I have a table, and there is no column which stores a field of when the record/row was added. How can I get the latest entry into this table? There would be two cases in this:
Loop through entire table and get the largest ID, if a numeric ID is being used as the identifier. But this would be very inefficient for a large table.
If a random string is being used as the identifier (which is probably very, very bad practise), then this would require more thinking (I personally have no idea other than my first point above).
If I have one field in each row of my table which is numeric, and I want to add it up to get a total (so row 1 has a field which is 3, row 2 has a field which is 7, I want to add all these up and return the total), how would this be done?
Thanks
1) If the id is incremental, "select max(id) as latest from mytable". If a random string was used, there should still be an incremental numeric primary key in addition. Add it. There is no reason not to have one, and databases are optimized to use such a primary key for relations.
2) "select sum(mynumfield) as total from mytable"
for the last thing use a SUM()
SELECT SUM(OrderPrice) AS OrderTotal FROM Orders
assuming they are all in the same column.
Your first question is a bit unclear, but if you want to know when a row was inserted (or updated), then the only way is to record the time when the insert/update occurs. Typically, you use a DEFAULT constraint for inserts and a trigger for updates.
If you want to know the maximum value (which may not necessarily be the last inserted row) then use MAX, as others have said:
SELECT MAX(SomeColumn) FROM dbo.SomeTable
If the column is indexed, MSSQL does not need to read the whole table to answer this query.
For the second question, just do this:
SELECT SUM(SomeColumn) FROM dbo.SomeTable
You might want to look into some SQL books and tutorials to pick up the basic syntax.

Universal SQL construct to retrieve the last row inserted

What would be the correct universal SQL construct to get the last row inserted (or it's primary key). The ID might be autogenerated by a sequence but I do not want to deal with the sequence at all! I need to get the ID by querying the table. Alternatively, INSERT might be somehow extended to return the ID. Assume I am always inserting a single row. The solution should work with most RDBMS!
the best way is to depend on the sequence like:
select Max(ID) from tableName
but If you don't want to deal with it, you can add new timestamp column to your table and then select max from that column.
like this way
select Max(TimestampField) from tableName

Periodic restarting auto numbering for SQL Server

I have a requirement for a program I'm working on to store job numbers as YY-###### with incrementing numbers starting at 000001 in each year preceded by the last two digits of the year.
The only method I've been able to come up with is to make a CurrentJob table and use an identity column along with the last two digits of the year and an ArchiveJob table and then combining the two via a union in a view. Then I'd have to copy the CurrentJob to ArchiveJob at the begining of the year and truncate CurrentJob.
Is there an easier way to restart the numbering (obviously not having it be an Identity column) in one table?
The client is closed on New Years so there should be no data entry at the change of the year (for a school).
An identity column is by far the fastest and most concurrent solution to generating sequential numbers inside SQL Server. There's no need to make it too complicated though. Just have one table for generating the identity values, and reset it at the end of the year. Here's a quick example:
-- Sequence generating table
create table SequenceGenerator (
ID integer identity(1, 1) primary key clustered
)
-- Generate a new number
insert into SequenceGenerator default values
select ##identity
-- Reset the sequence
truncate table SequenceGenerator
if ident_current('SequenceGenerator') <> 1 begin
dbcc checkident('SequenceGenerator', reseed, 0)
dbcc checkident('SequenceGenerator', reseed)
end else begin
dbcc checkident('SequenceGenerator', reseed, 1)
end
There is a similar question #761378.. (Note: it uses MySql but the principle is the same)
The accepted answer suggested using a second table to manage the current ID.
However the most popular question was to not do this! Please note HLGEM's answer on the post for reasons why not to.
You can use the "reseed" command from here to reset the starting value.