In my database there is a column for ID where is set to "auto incremental"
So when I delete a row where ID = 2 for example and insert a new row ID takes value of 3.
The question is how to set ID return to 2 and not 3 on action Delete?
I am using Microsoft SQL Server 2012.
As most other auto-increment implementations in other databases, SQL Server's identity columns does not offer any option to "fill the gaps" left when numbers are wasted (which may happen not only when rows are deleted, but also possibly when a transaction is rolled back or when the server restarts).
This is clearly specified in the documentation:
The identity property on a column does not guarantee the following:
[...]
Reuse of values - For a given identity property with specific seed/increment, the identity values are not reused by the engine.
If, for displaying purpose, you want a constantly increasing value that resets when rows are deleted, you can use row_number() in a select query:
select t.*, row_number() over(order by id) new_id
from mytable t
If you are going to use that on a regular bases, you can create a view, that you can then query instead of the original table:
create view myview as
select t.*, row_number() over(order by id) new_id
from mytable t;
select * from myview;
You can use the CHEKIDENT database console command to change the identity value of the table after you delete, although you should use this only if you are deleting the last record.
DBCC CHECKIDENT('YourTable', RESEED, 2)
I don't think you actually want to do this. You may not see it now but having an identity column that will always identify the row that was deleted is a good thing.
If you need a column to behave a different way just create a new column and apply business rules to have it work the way you want.
Call it ID_NOGAP and then make sure that there are never gaps. You can do this in the data access layer or with triggers on the DB (not recommended.)
Related
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
I have a SQLite table sorted by column ID. But I need to sort it by another numerical field called RunTime.
CREATE TABLE Pass_2 AS
SELECT RunTime, PosLevel, PosX, PosY, Speed, ID
FROM Pass_1
The table Pass_2 looks good, but I need to renumber the ID column from 1 .. n without resorting the records.
It is a principle of SQL databases that the underlying tables have no natural or guaranteed order to their records. You must specify the order in which you want to see the records when SELECTing from a table using an ORDER BY clause.
You can obtain the records you want using SELECT * FROM your_table ORDER BY RunTime, and that is the correct and reliable way to do this in any SQL database.
If you want to attempt to get the records in Pass_2 to "be" in RunTime order, you can add the ORDER BY clause to the SELECT you use to create the table but remember: you are not guaranteed to get the records back in the order in which they were added to the table.
When might you get the records back in a different order? This is most likely to happen when your query can be answered using columns in a covering index -- in that case the records are more likely to be returned in index order than any "natural" order (but again, no guarantees with an ORDER BY clause).
If you want a new ID column starting at 1, then use the ROW_NUMBER() function. Instead of ID in your query use this ROW_NUMBER() OVER(ORDER BY Runtime) AS ID.... This will replace the old ID column with a freshly calculated column
I have one table CSBCA1_5_FPCIC_2012_EES207201222743, having two columns employee_id and employee_name
I have used following query
SELECT ROW_NUMBER() OVER (ORDER BY EMPLOYEE_ID) AS ID, EMPLOYEE_ID,EMPLOYEE_NAME
FROM CSBCA1_5_FPCIC_2012_EES207201222743
But, it returns the rows in ascending order of employee_id, but I need the rows in order they were inserted into the table.
SQL Server does not track the order of inserted rows, so there is no reliable way to get that information given your current table structure. Even if employee_id is an IDENTITY column, it is not 100% foolproof to rely on that for order of insertion (since you can fill gaps and even create duplicate ID values using SET IDENTITY_INSERT ON). If employee_id is an IDENTITY column and you are sure that rows aren't manually inserted out of order, you should be able to use this variation of your query to select the data in sequence, newest first:
SELECT
ROW_NUMBER() OVER (ORDER BY EMPLOYEE_ID DESC) AS ID,
EMPLOYEE_ID,
EMPLOYEE_NAME
FROM dbo.CSBCA1_5_FPCIC_2012_EES207201222743
ORDER BY ID;
You can make a change to your table to track this information for new rows, but you won't be able to derive it for your existing data (they will all me marked as inserted at the time you make this change).
ALTER TABLE dbo.CSBCA1_5_FPCIC_2012_EES207201222743
-- wow, who named this?
ADD CreatedDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;
Note that this may break existing code that just does INSERT INTO dbo.whatever SELECT/VALUES() - e.g. you may have to revisit your code and define a proper, explicit column list.
There is a pseudocolumn called %%physloc%% that shows the physical address of the row.
See Equivalent of Oracle's RowID in SQL Server
SQL does not do that. The order of the tuples in the table are not ordered by insertion date. A lot of people include a column that stores that date of insertion in order to get around this issue.
I have a table with 4 columns. The first column is unique for each row, but it's a string (URL format).
I want to update my table, but instead of using "WHERE", I want to update the rows in order.
The first query will update the first row, the second query updates the second row and so on.
What's the SQL code for that? I'm using Sqlite.
Edit: My table schema
CREATE table (
url varchar(150),
views int(5),
clicks int(5)
)
Edit2: What I'm doing right now is a loop of SQL queries
update table set views = 5, click = 10 where url = "http://someurl.com";
There is around 4 million records in the database. It's taking around 16 seconds in my server to make the update. Since the loop update the row in order, so the first query update the first row; I'm thinking if updating the rows in order could be faster than using the WHERE clause which needs to browse 4 million rows.
You can't do what you want without using WHERE as this is the only way to select rows from a table for reading, updating or deleting. So you will want to use:
UPDATE table SET url = ... WHERE url = '<whatever>'
HOWEVER... SqlLite has an extra feature - the autogenerated column, ROWID. You can use this column in queries. You don't see this data by default, so if you want the data within it you need to explicitly request it, e.g:
SELECT ROWID, * FROM table
What this means is that you may be able to do what you want referencing this column directly:
UPDATE table SET url = ... WHERE ROWID = 1
you still need to use the WHERE clause, but this allows you to access the rows in insert order without doing anything else.
CAVEAT
ROWID effectively stores the INSERT order of the rows. If you delete rows from the table, the ROWIDs for remaining rows will NOT change - hence it is possible to have gaps in the ROWID sequence. This is by design and there is no workaround short of re-creating the table and re-populating the data.
PORTABILITY
Note that this only applies to SQLite - you may not be able to do the same thing with other SQL engines should you ever need to port this. It would be MUCH better to add an EXPLICIT auto-number column (aka an IDENTITY field) that you can use and manage.
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