-
Notifications
You must be signed in to change notification settings - Fork 53
Allow AUTOINCREMENT with compound PRIMARY KEY
#301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
80ab70f to
1f8ebce
Compare
1f8ebce to
c6074c6
Compare
brandonpayton
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JanJakes I think this will work for most cases, but with this scheme, there are queries for the test table that work with MySQL but not SQLite.
For the test table
CREATE TABLE t1 (id INT AUTO_INCREMENT, name VARCHAR(32), PRIMARY KEY(id, name))'
In MySQL, you can INSERT two different rows with the same id as long as name is different:
MariaDB [149697504]> CREATE TABLE t1 (id INT AUTO_INCREMENT, name VARCHAR(32), PRIMARY KEY(id, name));
Query OK, 0 rows affected (0.002 sec)
MariaDB [149697504]> INSERT INTO t1 (id, name) VALUES (4, 'four');
Query OK, 1 row affected (0.001 sec)
MariaDB [149697504]> INSERT INTO t1 (id, name) VALUES (4, 'another value');
Query OK, 1 row affected (0.001 sec)
MariaDB [149697504]> SELECT * FROM t1;
+----+---------------+
| id | name |
+----+---------------+
| 4 | another value |
| 4 | four |
+----+---------------+
But in the SQLite scheme, it does not work because id is constrained to be unique on its own:
sqlite> CREATE TABLE t2 (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(32));
sqlite> CREATE UNIQUE INDEX compound_primary ON t2 (id, name);
sqlite> INSERT INTO t2 (id, name) VALUES (4, 'four');
sqlite> INSERT INTO t2 (id, name) VALUES (4, 'another value');
Runtime error: UNIQUE constraint failed: t2.id (19)
sqlite>
Is there another way we could approach this? What do you think?
|
@brandonpayton Thanks for the in-depth feedback!
Yeah, it's definitely a limitation of this simple approach, but I think it's probably fine to keep this limitation, at least until we encounter some real-life scenario where this causes issues. My reasoning behind this is the following (also documented in a comment):
In other words, having a primary key that is a combination of autoincrement and some other columns seems pretty unusual—normally one either wants a column to be automatically incremented or manually inserted.
Originally, I was thinking along these lines (and didn't consider such an approach to be worth it):
So far so good, but here's the problem: ALTER TABLE t AUTO_INCREMENT = 123;Now, we'd need the trigger to actually maintain a modifiable sequence somewhere, and it gets all a bit too complicated. Unfortunately, Therefore, I went on with the assumption that an autoincrement column might be unique anyway. What do you think? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brandonpayton Thanks for the in-depth feedback!
In MySQL, you can INSERT two different rows with the same id as long as name is different:
But in the SQLite scheme, it does not work because id is constrained to be unique on its own:Yeah, it's definitely a limitation of this simple approach, but I think it's probably fine to keep this limitation, at least until we encounter some real-life scenario where this causes issues.
@JanJakes This sounds good. Thanks for explaining and discussing an alternative possibility.
I think this is good to go!
In MySQL, a compound
PRIMARY KEYcan have anAUTOINCREMENTcolumn, when it is the first column in the key.SQLite doesn't support this, but we can emulate it as follows:
PRIMARY KEY.Since this is the column that also has
AUTOINCREMENT, it reasonable to assume that its values are unique.UNIQUEkey for all thePRIMARY KEYcolumns.This is to preserve the index of the compound key.
The actual fix is best viewed in the second commit.