I have a production database with few million rows all using randomly generated GUIDs using a default value of NewID() as the primary key.
I am thinking of using the Sequential NewIDs going forward.
How will SQL Server know while generating the GUIDs in sequence that it did not already create that GUID when it was randomly generating using NEWID()?
It sounds like you're considering using NEWSEQUENTIALID() as the new default value.
Don't worry about the scenario of duplicates. The PK constraint on that column guarantees that a collision isn't going to happen. You aren't guaranteed that a new sequential GUID will be 'higher' anyway:
Creates a GUID that is greater than any GUID previously generated by this function on a specified computer since Windows was started. After restarting Windows, the GUID can start again from a lower range, but is still globally unique.
Some relevant information that may help you at Microsoft Connect : NEWSEQUENTIALID() is Not Sequential
Related
I am creating a Django app where the primary keys are AutoFields. i.e. I am not manually assigning any field as primary key in my models.
I need to use mySQL.
I will need to export all the data to excel or perhaps another django app from time to time. Therefore the primary keys must be unique to be able to identify new records or records to be deleted in excel/other app.
However, I have read that mySQL autoincrement counter resets to the max key when database restarts. This will result in reassignment of keys if the latest records were deleted.
I need to avoid this. No key should be reassigned.
How can this be done?
MySQL 8.0 now keeps the last auto-increment per table persistently. So it remembers between restarts, and does not reset the auto-increment.
https://www.percona.com/blog/2018/10/08/persistence-of-autoinc-fixed-in-mysql-8-0/
Hibernate has an identifier generation strategy called native that selects identity, sequence or hilo depending upon the capabilities of the underlying database. I used MySQL with hibernate.hbm2ddl.auto=update which generated id BIGINT(20) NOT NULL AUTO_INCREMENT for id property of Long Java data type.
I am trying to understand how did Hibernate choose AUTO_INCREMENT when it used SchemaExport tool. Is AUTO_INCREMENT the default primary key generation strategy for MySQL?
Could somebody help me understand it?
Hibernate when selecting the key generation mechanism in native mode, will try to choose the best mechanism available in the database. In the case of MySQL, auto increment is available and Hibernate uses it instead of a sequence, because the auto increment mechanism is slightly better altough sequences also work fine.
The reason why it's better is that it's possible in one single JDBC prepared statement, for example an insert, to do an insert AND retrieve the generated key without querying the database - see here for further details.
In the case of sequences, Hibernate has to first call the sequence at some point and then use the value or the result of it's use in a formula to populate the insert key and then issue the insert.
The autoincrement spares this extra roundtrip to the database needed to increment the sequence, and that is the reason why Hibernate prefers it in the case of MySQL.
I am using Cayenne to add records to a MySQL database, and I am seeing some strange behavior.
When I run my application, I create a DataContext, perform a series of adds, then close the application. This works out well, because I am using an integer for a primary key, and when I add a record to the database, the key automatically increments. For some reason, it starts at 200 for the first record, then goes to 201 for the second record, etc.
If, however, I stop the application, then run it again, the primary key starts at 200 again! This, of course, causes an exception to be thrown because a new record ends up having a duplicate primary key. It is looking like when I create a new object using the DataContext's newObject() after starting my application, Cayenne does not "remember" how far the primary key was incremented when the application was previously run.
Does anyone know what is causing this reset of the primary key values, and (more importantly) how to stop it from happening??? Or have I found a bug in the current version of Cayenne? I am using Version 3.0.2.
Someone please advise...
The last used PK for a given table is stored in a special table called AUTO_PK_SUPPORT. Please check the contents of this table between the restarts of your app. Also check you application Cayenne logs for reads and writes to AUTO_PK_SUPPORT. This should give you an idea of what's happening.
Aside from that you might switch to auto-increment PK (see "Primary Key Provided by Database" section here). MySQL supports auto-incremented PK columns and if you have an option of altering the schema, this IMO is the cleanest PK generation strategy out of all available. (And it doesn't require AUTO_PK_SUPPORT).
I created a table using the below definition for a Teradata identity column:
ID INTEGER GENERATED BY DEFAULT AS IDENTITY
(START WITH 1
INCREMENT BY 1
MINVALUE 0
MAXVALUE 100000000
NO CYCLE),
----
UNIQUE PRIMARY INDEX ( ID )
For several months, the ID column has been working properly, automatically generating a unique value for the column. Over the past month, however, ELMAH has been intermittently reporting the following exception from our .NET 4.0 ASP.NET app:
Teradata.Client.Provider.TdException: [Teradata Database] [2801] Duplicate unique prime key error in DATABASENAME.TABLENAME.
I was able to replicate it by opening SQL Assistant and inserting a bunch of records into the table with raw SQL. As expected, most of the time it would insert successfully, but other times it would throw the above exception.
It appears that this error is occuring because Teradata is trying to generate a value for this column that it has previously generated.
Does anyone have any idea how to get to the bottom of what's happening? At the very least, I'd like some way to debug the issue a bit deeper.
I would suggest changing the definition of your identity column to GENERATED ALWAYS to prevent the application or ETL process from supplying a value that could have been used. In fact, it is recommended by Teradata that if you are using your IDENTITY column as part of a UPI that it should be defined as GENERATED ALWAYS ... NO CYCLE
EDIT:
If your business requirements are such that you must be able to provide a value I would also consider using a domain that is outside the range of values you have set aside for the IDENTITY column. You can use a negative domain or a range that is an order of magnitude beyond that of the IDENTITY column. Personal preference would be to use a negative domain.
I have an app where depending on the type of transaction being added or updated, the ticket number may or may not increment. I can't use a SERIAL datatype for ticket number because it would increment regardless of the transaction type, so I defined ticket number as an INT. So in a multi-user environment if user A is adding or updating a transaction and user B is also doing the same, I test for tran type and if next ticket number is required, then
LET ticket = (SELECT MAX(ticket) [WITH ADDLOCK or UPDLOCK?] FROM transactions) + 1
However this has to be done exactly when the row is being committed or troubles will begin. Can you think of a better way of doing this with: Informix, Oracle, MySQL, SQL-Server, 4Js/Genero or other RDBMS? This is one main factor which will determine what RDBMS I'm going to re-write my app in.
With the Informix DBMS, the SERIAL column will not change after it is inserted; indeed, you cannot update a SERIAL value at all. You can insert a new one with either 0 as the value - in which case a new value is generated - or you can insert some other value. If the other value already exists and there is a unique constraint, that will fail; if it does not exist, or if there is no unique constraint on the serial column, then it will succeed. If the value inserted is larger than the largest value previously inserted, then the next number to be inserted will be one larger again. If the number inserted is smaller, or negative, then there is no effect on the next number.
So, you could do your update without changing the value - no problem. If you need to change the number, you will have to do a delete and insert (or insert and delete), where the insert has a zero in it. If you prefer consistency and you use transactions, you could always delete, and then (re)insert the row with the same number or with a zero to trigger a new number. This assume you have a programming language running the SQL; I don't think you can tweak ISQL and Perform to do that automatically.
So, at this point, I don't see the problem on Informix.
With the appropriate version of IDS (anything that is supported), you can use SEQUENCE to control the values inserted too. This is based on the Oracle syntax and concept; DB2 also supports this. Other DBMS have other equivalent (but different) mechanisms for handling the auto-generated numbers.
That's what sequences were created for and which is supported by most databases (MySQL being the only one that does not have sequences - not 100% sure about Informix though)
Any algorithm that relies on the SELECT MAX(id) anti-pattern is either dead-slow in a multi-user environment or will simply not work correctly in a multi-user environment.
If you need to support MySQL as well, I'd recommend to use the "native" "auto increment" type in each database (serial for PostgreSQL, auto_increment for MySQL, identity for SQL Server, sequence + trigger in Oracle and so on) and let the driver return the generated ID value
In JDBC there is a getGeneratedKeys() method and I'm sure other interfaces have something similar.
From your tags it's hard to tell what database you are using.
For SQL Server (since it's listed) I suggest
ticket_num = (SELECT MAX(ticket_number) FROM transactions with (updlock)) + 1