Identity out of order with system versioned table - sql-server

I'm using system-versioned (temporal) tables with an identity column and noticed that sometimes the start time of a row in the history table has a higher identity value than a row with a later start time. See example below:
StartTime
EndTime
Identity
2022-09-21 14:10:25.4181267
2022-09-21 16:32:14.5724582
2
2022-09-21 14:10:26.1524526
2022-09-21 15:46:19.6136239
1
Is this because of overlapping transactions - i.e one row "claimed" the earlier identity value but was then inserted slightly after another set of values?

From the document you linked
INSERTS: The system sets the value for the ValidFrom column to the begin time of the current transaction...
But IDENTITY columns take their values at the moment of insertion. So yes, there may be an overlap.

Related

Adding last change timestamp to a table in snowflake

I have a lots of tables in Snowflake that I am updating them ( basically re-creating them) every day with a python script.
I can see the timestamp of the last time those tables have been changed in information schema of my database but how can I add the column or that information to one of our tables?
Assume that I have a table customer and I want to be able to see when was the last time that each row of that table has been changed. I can see this timestamp here:
SELECT CONVERT_TIMEZONE('Etc/GMT+9','UTC',last_altered) AS last_changed
FROM "XXXX"."INFORMATION_SCHEMA"."TABLES"
WHERE table_name='CUSTOMERS';
how to add this information to customer table?
If you would like to see that information your python program should add that information as additional columns in each row. We used to call these columns as 'WHO COLUMNS', below are the WHO COLUMNS that we added to each table in the final schema
Last Updated TimeStamp
Last Updated User
Creation Timestamp
The best option would be to add an additional audit column to the customer table with a default value as current_timestamp
Example:
CREATE TABLE CUSTOMER (column1 varchar, insert_date timestamp default current_timestamp())
In this example you can use insert_date to track when that record is inserted. The column would be auto-populated whenever you are inserting a row like this.
INSERT INTO CUSTOMER(column1) VALUES ('test')

SSIS Lookup Suggestion

I have a task to Generate a Derived Column (RestrictionID) from a table and add it to a source table if 6 columns on both tables match. The 6 columns include (Country, Department, Account .etc) I decided to go with the SSIS Lookup and generate the Derived column when there's a match. This ID also has a time and amount Limit. Once all the records have ID's, I'm supposed to calculate a running total based on the ID to enforce the limits which is the easy part.
The only problem is this Lookup table changes almost daily and any or all of the 6 columns can have NULLS. Even the completely null rows have an Id. Nulls mean the Restriction is open. eg. If the Country column on one record on the lookup table is null, then the ID of that record can be assigned to records with any country on the source. If one row on the lookup has all null columns, then this is completely open and all records on the source qualify for that ID. The Source table doesn't have NULLS.
Please assist if possible
Thanks
If NULL means any and ignore column in lookup then add this to your where:
use a stored proc and pass your values in and return:
select lookup.ID
from lookup
where #Country = isnull(lookup.Country,#Country) //If lookup inull then it refers to itself creating a 1=1 scenario
and #Department = isnull(lookup.Department,#Department)
and ...

Find the last applied seed value on a table in sql server 2012

I created a table and inserted 4 rows into it. I ran the below query
SELECT seed_value as SeedValue, last_value as identityValue
FROM sys.identity_columns
WHERE object_id=OBJECT_ID('ALJtest1')
and got the result as
SeedValue| identityValue
-------------------------
1 | 4
Then I reseeded the table using
DBCC CHECKIDENT('DBO.ALJtest1', RESEED, 10)
When I ran the below query this time
SELECT seed_value as SeedValue, last_value as identityValue
FROM sys.identity_columns
WHERE object_id=OBJECT_ID('ALJtest1')
I got the result as
SeedValue| identityValue
-------------------------
1 | 10
Is there a way to find the last applied seed value on a table in SQL Server 2012?
RESEED, despite the name, doesn't change the identity's seed value, instead it simply sets the next identity value to generate. There is no way to change an identity column's actual seed value after it's created. From the documentation:
The seed value is the value inserted into an identity column for the
very first row loaded into the table. All subsequent rows contain the
current identity value plus the increment value where current identity
value is the last identity value generated for the table or view.
You cannot use DBCC CHECKIDENT to perform the following tasks:
Change the original seed value that was specified for an identity column when the table or view was created.
Reseed existing rows in a table or view.
To change the original seed value and reseed any existing rows, you
must drop the identity column and recreate it specifying the new seed
value. When the table contains data, the identity numbers are added to
the existing rows with the specified seed and increment values. The
order in which the rows are updated is not guaranteed.
So to answer your question: no, there is no way to know the last value specified in a DBCC CHECKIDENT(..., RESEED), because the current identity value may have already changed after inserts.

Trying to reset Identity value for SQL Azure DB Table column

I am using SQL Azure. I have a deployment DB and a test DB
I would like to add some new lookup records to the Test DB, to test new code.
Initially My Deployment DB's Identity was set to 200000+ for the PKs, and my Test DB to 100000+, to prevent PK collisions when syncing using such tools as Redgates' SQL data compare.
Unfortunately I made a mistake, and copied the Deployment DB as the new Test DB, since we required a more up to date dataset. As a result my Test DB now starts at 200000+. So I now have the risk of conflicts when syncing with the Deployment DB.
I would normallly just use:
DBCC CHECKIDENT('TableName', RESEED, 105000)
However SQL Azure does not support this.
I have come across a workaround:
set identity_insert TableName on -- this basically turns off IDENTITY
INSERT INTO TableName(id, name) VALUES (104999,'Test Reset Identity Start 104999') -- so we can jam any value for column ID
set identity_insert TableName off -- then turn it back on
INSERT INTO TableName(name) VALUES ('Test Reset Identity End') -- ID starts at 105000, in theory, from this point
SELECT * FROM TableName
However the new Identify value always seems to take the highest PK in the table as the last seed, rather than the PK value from the last inserted record.
I would rather not rebuild the table.
Is there another approach to resetting the identity value for my situation, ie to a lesser number ie 104999 rather the current 204999?
Thanks in advance.
EDIT 1
It may be I can only check the identity value to a value greater than the current value ie to say 206000 ?
EDIT 2
Perhaps there is an argument that Identity value should never be reseed to less than the max PK value, even if there is 100,000 spare numbers, as one day you will get a collision.

Some tables id column do not auto increment despite being identity

I am troubleshooting a db (not my forte) that has some tables that are auto incrementing on the id column and some tables are not?
Now all the tables are set as identity and marked to disallow null. I am using SSMS what else can I check or do to get these tables back to auto incrementing?
TIA
Interestingly to me...probably old news to you guys. The issue had to do with existing data. So for example a table that had 100 rows in did NOT have the identity column setup. So I would go in and make it an identity with a seed of 1 incrementing 1. Well the seed was somehow having trouble because there was already 100 rows in there. So for all my tables I had to do a row count and seed the identity from the next row. Now it is working as expected.
Having an IDENTITY column is pretty straightforward for a table, and if you are not seeing the auto incrementing behavior of a column on inserts, then I'd first verify that your column is indeed an IDENTITY column:
use <Your Database Name>;
go
select
name,
is_identity
from sys.columns
where object_id = object_id('<Your Table Name>')
order by column_id;
Substitute <Your Database Nam> and <Your Table Name> for their appropriate values.
The other possibility is that data that "appears" to be non-incrementing could have been pushed out to that with a session that set identity insert and pushed out explicit values.
ALTER TABLE YourTable MODIFY COLUMN YourTable_id int(4) auto_increment

Resources