Error on adding PRIMARY KEY to existing table [duplicate] - mariadb

I keep getting an error "Incorrect index name 'f7'" using MySQL and I've narrowed it down to the following:
First I create the table,
CREATE TABLE testTable (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
f7 INTEGER NOT NULL,
FOREIGN KEY (f7) REFERENCES testTable2 (id) ON DELETE CASCADE ON UPDATE CASCADE,
) ENGINE=InnoDB;
And then elsewhere,
ALTER TABLE testTable ADD UNIQUE f7;
This has led me to believe that this has to do with a duplicate index (?) I just can't figure out how to fix it. Many thanks.

Give it a name, so it doesn't conflict with the foreign Key index
ALTER TABLE `testtable` ADD UNIQUE INDEX `foo` (`f7`);

An incorrect index name error is given when you're attempting to create a new index with the same name as an existing index.
In MySQL, when you create a foreign key, as you're doing with FOREIGN KEY (f7) REFERENCES testTable2 (id) ON DELETE CASCADE ON UPDATE CASCADE, an index is auto-created as well. In this case, the name is defaulted to f7.
The foreign key is created as a non-unique index; your second command: ALTER TABLE testTable ADD UNIQUE (f7); will make this index unique - not add a second one.
To verify what indexes already exist on the table, you can use the following:
SHOW INDEXES FROM testTable;
If you're receiving this error, there is likely additional code elsewhere that is attempting to create an index named f7. You can attempt to find it, or change your CREATE TABLE syntax to name the key something different so that it doesn't cause conflicts:
FOREIGN KEY fk_testTable_f7 (f7) REFERENCES testTable2 (id) ON DELETE CASCADE ON UPDATE CASCADE
In this example, I used fk_testTable_f7 and you should now have a non-unique index on the table named fk_testTable_f7. To make it unique, you can use your existing ALTER command as you want the column to be unique - not the foreign key itself.

Related

In SQLite, how do I alter a table to add a column with default null and foreign key constraint?

The SQLite doc says:
It is not possible to use the "ALTER TABLE ... ADD COLUMN" syntax to
add a column that includes a REFERENCES clause, unless the default
value of the new column is NULL.
I can't get my ALTER TABLE statement to work, it looks like this:
ALTER TABLE Customers ADD COLUMN AddressID INTEGER DEFAULT NULL FOREIGN KEY REFERENCES MasterAddress (AddressID);
I can see references to workarounds that create a constraint at CREATE TABLE time and bouncing the data through a new table but I would prefer altering my existing table. Is this possible?
I have set PRAGMA foreign_keys = ON.
DEFAULT NULL is the default; you do not need to specifiy it.
FOREIGN KEY is used to introduce a table constraint, but ALTER TABLE supports only column constraints. The syntax for a column constraint does not have the FOREIGN KEY:
ALTER TABLE Customers ADD AddressID INTEGER REFERENCES MasterAddress(AddressID);

How to get the names of foreign key constraints in SQLite?

Does SQLite indeed have a limitation that it is not possible to retrieve the name of a foreign key? I am asking because I couldn't find this limitation mentioned anywhere in their documentation.
For example, I run the following script:
CREATE TABLE
users (
id INTEGER NOT NULL PRIMARY KEY,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL
) ;
CREATE TABLE
orders (
id INTEGER NOT NULL PRIMARY KEY,
user_id INTEGER NOT NULL,
CONSTRAINT fk_users FOREIGN KEY (user_id) REFERENCES users(id)
) ;
Now I would like to check that the key "fk_users" was created indeed, so I run the following PRAGMA:
PRAGMA foreign_key_list(orders);
I would expect to see the name of my foreign key in the first column, but I am seeing some "0" value instead. Moreover, if I create multiple foreign keys with custom names, they are all called either "0" or "1".
Is this indeed a limitation of SQLite, or am I missing something?
There is no mechanism to extract the constraint name.
The table sqlite_master stores a CREATE command in the column "sql". You could query that command and do some parsing to extract the name of the foreign key. An example for a combined foreign key that works for me:
SELECT sql FROM sqlite_master WHERE name = 'song'
yields
CREATE TABLE "song" (
"songid" INTEGER,
"songartist" TEXT,
"songalbum" TEXT,
"songname" TEXT,
CONSTRAINT "fk__song_album" FOREIGN KEY ("songartist", "songalbum") REFERENCES "album" ("albumartist", "albumname")
)
and contains the name "fk__song_album" of the foreign key.
If one alters the foreign key with a query, the content of the sql column is modified/updated:
The text in the sqlite_master.sql column is a copy of the original CREATE statement text that created the object, except normalized as described above and as modified by subsequent ALTER TABLE statements. The sqlite_master.sql is NULL for the internal indexes that are automatically created by UNIQUE or PRIMARY KEY constraints.
https://www.sqlite.org/fileformat2.html
Extra tip:
In order to see the foreign key information in Navicat (Lite) ... right click on a table and choose "Design table". Then select the foreign keys tab.

SQLlite: strange "Abort due to constraint violation"

I'm trying to rename a column of a table. I have a lot of tables with the word "couleur" and I renamed "manually" to "bulle".
I've successfully renamed main_groupecouleurs to main_groupebulles. Now i'm working on main_groupe. I'm trying to rename groupe_couleurs_id to groupe_bulles_id
The SQL is quite self-explaining:
BEGIN TRANSACTION;
DROP INDEX main_groupe_fc5cee5b;
CREATE TABLE main_groupe7e12
(
id INTEGER PRIMARY KEY NOT NULL,
description TEXT NOT NULL,
exemple TEXT,
groupe_bulles_id INTEGER DEFAULT NULL,
reference TEXT,
FOREIGN KEY (groupe_bulles_id) REFERENCES main_groupebulles(id)
DEFERRABLE INITIALLY DEFERRED
);
CREATE UNIQUE INDEX main_groupe_fc5cee5b ON main_groupe7e12 (groupe_bulles_id);
INSERT INTO main_groupe7e12(id, description, exemple, groupe_bulles_id, reference)
SELECT id, description, exemple, groupe_couleurs_id, reference
FROM main_groupe;
DROP TABLE main_groupe;
ALTER TABLE main_groupe7e12 RENAME TO main_groupe;
COMMIT;
When I run it, I get:
[SQLITE_CONSTRAINT] Abort due to constraint violation
(UNIQUE constraint failed: main_groupe7e12.groupe_bulles_id)
This means (I think I'm wrong here but I dont know what I'm missing) that it tries to insert some groupe_couleurs_id that are not in the referring table (= main_groupebulles). Thus I tried to see in the original table the problem:
SELECT * FROM main_groupe WHERE groupe_couleurs_id NOT IN (
SELECT id FROM main_groupebulles
);
I got no rows! What am I missing?
You have an UNIQUE index on your groupe_bulles_id column but based on the comments, there are a lot of valid duplicate values for that column coming from main_groupe.groupe_couleus_id and that causes the constraint violation.
Since having duplicate values is what you want, remove the UNIQUE from the CREATE UNIQUE INDEX ....

invalid alter table option while modify foreign key

I want to modify the update option of one foreign key.
For this I executed this command:
alter table testusers.ORDERS
DROP CONSTRAINT ORDER_FK_2,
ADD CONSTRAINT ORDER_FK_2 FOREIGN KEY(FK_PRODUCER_ID) REFERENCES testuser.PRODUCER (producer_id)
ON UPDATE CASCADE ON DELETE CASCADE;
If I execute this, there is the following error:
SQL-Fehler: ORA-01735: Ungültige Option ALTER TABLE
01735. 00000 - "invalid ALTER TABLE option"
There is no comma separated list for the alter table according to documentation syntax diagram http://docs.oracle.com/cd/B28359_01/server.111/b28286/clauses002.htm#CJAEDFIB
create table orders(order_id number, fk_producer_id number, CONSTRAINT order_pk PRIMARY KEY (order_id));
create table producer(producer_id number, CONSTRAINT producer_pk PRIMARY KEY (producer_id));
alter table orders
ADD CONSTRAINT ORDER_FK_2 FOREIGN KEY( FK_PRODUCER_ID)
REFERENCES PRODUCER (producer_id) ;
alter table orders
DROP CONSTRAINT ORDER_FK_2;
alter table orders
ADD CONSTRAINT ORDER_FK_2 FOREIGN KEY( FK_PRODUCER_ID)
REFERENCES PRODUCER (producer_id) ;
Ahm, yes, and I could not find any ON UPDATE CASCADE syntax either. But I am sure you can work it out now. Otherwise drop a little comment or post a new question.

SQLITE: Unable to remove an unnamed primary key

I have a sqlite table that was originally created with:
PRIMARY KEY (`column`);
I now need to remove that primary key and create a new one. Creating a new one is easy, but removing the original seems to be the hard part. If I do
.indices tablename
I don't get the primary key. Some programs show the primary key as
Indexes: 1
[] PRIMARY
The index name is typically in the [].
Any ideas?
You can't.
PRAGMA INDEX_LIST('MyTable');
will give you a list of indices. This will include the automatically generated index for the primary key which will be called something like 'sqlite_autoindex_MyTable_1'.
But unfortunately you cannot drop this index...
sqlite> drop index sqlite_autoindex_MyTable_1;
SQL error: index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped
All you can do is re-create the table without the primary key.
I the database glossary; a primary-key is a type of index where the index order is typically results in the physical ordering of the raw database records. That said any database engine that allows the primary key to be changed is likely reordering the database... so most do not and the operation is up to the programmer to create a script to rename the table and create a new one. So if you want to change the PK there is no magic SQL.
select * from sqlite_master;
table|x|x|2|CREATE TABLE x (a text, b text, primary key (`a`))
index|sqlite_autoindex_x_1|x|3|
You'll see that the second row returned from my quick hack has the index name in the second column, and the table name in the third. Try seeing if that name is anything useful.

Resources