SQLite :How can i add primary key to table using alter? - sqlite

Im trying to alter my table "Materiel" for make a primary key.,but this instruction is not working.
ALTER TABLE "MATERIEL" ADD CONSTRAINT "MATERIEL_PK" PRIMARY KEY ("MATRICULE")
This is stack trace:
[00:22:39] Error while executing SQL query on database 'Data': near
"CONSTRAINT": syntax error

Of course it won't work - that syntax is not supported by SQLite3 (see https://sqlite.org/lang_altertable.html). To do this, you need to re-create the table to include the constraint.

Related

SQLiteException no such table: main.*_temp

I have a Xamarin.Forms app that uses a SQLite database locally on the device. Here's some sample data structure:
Table x: id, name
Table y: id, name
Table x_y: id, x_id, y_id
Since SQLite doesn't support altering columns, one of the schema updates we sent down in a patch did the following:
Rename table x to x_temp
Create new/updated table x
Insert all data from table x_temp into table x
Drop table if exists x
That seems to work just fine. However, when I'm attempting to run an insert statement on table x_y, I am getting a SQLite exception: "no such table: main.x_temp".
When I look at the SQLite query string while debugging there is no mention of table x_temp whatsoever. So, if I delete the entire database and re-create everything the insert works just fine.
I'm from a MSSQL background, am I not understanding something about SQLite in general? Is the foreign key constraint from table x_y trying to reference x_temp because I renamed the original table (I may have just answered my own question)? If that's the case, surely there is a way around this without having to cascade and re-create every table?
Any input would be appreciated. Thanks!
I believe that your issue may be related to the SQlite version in conjunction with whether or not Foreign Key Support has been turned on.
That is the likliehood is that :-
Is the foreign key constraint from table x_y trying to reference
x_temp because I renamed the original table (I may have just answered
my own question)?
Would be the issue, as you likely have Foreign Key Support turned on as per :-
Prior to version 3.26.0 (2018-12-01), FOREIGN KEY references to a table that is renamed were only edited if the PRAGMA foreign_keys=ON, or in other words if foreign key constraints were begin enforced.
With PRAGMA foreign_keys=OFF, FOREIGN KEY constraints would not be changed when the table that the foreign key referred to (the "parent table") was renamed.
Beginning with version 3.26.0, FOREIGN KEY constraints are always converted when a table is renamed, unless the PRAGMA legacy_alter_table=ON setting is engaged. The following table summaries the difference:
SQL As Understood By SQLite - ALTER TABLE
If that's the case, surely there is a way around this without having
to cascade and re-create every table?
Yes, as the latest version of SQlite on Android is 3.19.0 (I believe), then you can turn Foreign Key support off using the foreign_keys pragma when renaming the table.
Note Foreign Keys cannot be turned off within a transaction.
See SQL As Understood By SQLite - ALTER TABLE and PRAGMA foreign_keys = boolean;

SQLite ON CONFLICT fails to work for v3.8.11.1 (which comes with ubuntu by default)

select sqlite_version();
INSERT INTO users (uuid, test_field) VALUES ('uuid1', '1.0);
INSERT INTO users (uuid) VALUES ('uuid1') ON CONFLICT(uuid) DO UPDATE SET test_field = '1.1';
The above results in:
3.8.11.1
OK
ERROR: near "ON": syntax error
Why is it failing to recognize the ON word of ON CONFLICT
The us of ON CONFLICT is what is termed as an UPSERT and was only introduced in SQLite 3.24.0.
as per :-
UPSERT is a special syntax addition to INSERT that causes the INSERT
to behave as an UPDATE or a no-op if the INSERT would violate a
uniqueness constraint. UPSERT is not standard SQL. UPSERT in SQLite
follows the syntax established by PostgreSQL. UPSERT syntax was added
to SQLite with version 3.24.0 (2018-06-04).
SQL As Understood By SQLite - upsert
As such it cannot be used in SQLite 3.8.11.1 and thus the SYNTAX error near ON as it's not a recognised keyword in that context.

MariaDB remove foreign key to temporary table

Context:
I'm trying to upgrade a concrete5 installation from version 8.3.2 to 8.4.1. The upgrade process fails during execution of this SQL statement:
ALTER TABLE AreaLayoutsUsingPresets ADD CONSTRAINT FK_7A9049A1385521EA FOREIGN KEY (arLayoutID) REFERENCES AreaLayouts (arLayoutID) ON UPDATE CASCADE ON DELETE CASCADE
With:
SQLSTATE[HY000]: General error: 1005 Can't create table `concrete5`.`#sql-215_264a4` (errno: 121 "Duplicate key on write or update")
Investigating my database revealed that in information_schema in INNODB_SYS_FOREIGN there is the following entry:
ID FOR_NAME REF_NAME N_COLS TYPE
concrete5/FK_7A9049A1385521EA concrete5/#sql-215_26264 concrete5/AreaLayouts 1 5
Problem:
Now my understanding is, that I cannot modify the information_schema as it isn't a database but just a tabular representation of the system.
I'm wondering how do I get rid of that foreign key entry. The table concrete5/#sql-215_26264 does not exist (I can't find it on my server, nor does alter table or drop table find that table (I've tried with #mysql50# prefix and without it)). So the straight forward way of alter table to drop the foreign key fails because it can't find the table.
I guess I could mess with the upgrade script so that it creates a new foreign key ID, but I'd rather get rid of that zombie in my database. I've already tried to disable the foreign key checks, which then resulted in an error, telling me that the key cannot be added to the system tables (because it's already in there).
Reinstalling is rarely a cure for anything; but I am glad that it fixed your situation.
Table names such as #sql_... usually come from crashing in the middle of an ALTER or similar DDL. Such files can be removed. information_schema is derived from looking at the files, so I think removing the files will kill the zombie entries.
either prefix the SQL import with SET FOREIGN_KEY_CHECKS=0;
or your append it to your query ALTER TABLE...DISABLE KEYS;
... and better dump the whole database before messing around.

Syntax error in creating trigger in sqlite

The following code causes a syntax error in SQLite.
I imagine this must be simple but I can't see it.
I have two tables, pages and items, linked through a text code. When this code in changed in pages table, I want it changed in items table too.
The SQLite version is quite old, 3.7.7.1, but I haven't seen such a problem in version history. This occurs on Windows, with PHP 5.3.1.
CREATE TABLE IF NOT EXISTS "efpage" ( "pageid" integer NOT NULL PRIMARY KEY, "psite" text NULL, "pgcode" text NULL );
CREATE TABLE IF NOT EXISTS "efitem" ( "itemid" integer NULL PRIMARY KEY , "isite" text NULL, "ititle" text NULL, "inpage" text NULL);
DROP TRIGGER IF EXISTS update_pagecode;
CREATE TRIGGER update_pagecode AFTER UPDATE OF pgcode ON efpage
BEGIN
UPDATE efitem SET inpage = new.pgcode WHERE inpage = old.pgcode;
END;
The resulting error is
ERROR near "pgcode": syntax error.
Trying different things, I saw that the syntax error is after "old.pgcode;"
As indicated by CL,
this is linked to the version of SQLite.
I use SQLite bundled with PHP on windows.
The next (answered) question for me is :
How to update the SQLite version bundled with PHP

Altering a column on SQLite after definition

I was following an SQLite tutorial where the goal is to create a simple student database from an UML diagram.
The first thing I did was copy your UML, then took a break. Upon return, I figured I'd get started from the UML while reloading your video, so the very first things I did was create the student and sex_type table as so:
sqlite> create table student(name VARCHAR(23),
...> sex CHARACTER(1),
...> id_number INTEGER PRIMARY KEY);
sqlite> create table sex_type(sex_id TEXT PRIMARY KEY, sex_type INTEGER);
But then I realized, I forgot to indicated that I want sex_id to be NOT NULL as well. I also forgot under the to ensure that Foreign Key(sex) references sex_type(sex_id).
I reviewed my SQL books, and recalled something known as the ALTER command. However, no matter how I slice it, I get something along these lines:
sqlite> alter table sex_type MODIFY column sex_id TEXT PRIMARY KEY NOT NULL;
Error: near "MODIFY": syntax error
sqlite> alter table sex_type CHANGE column sex_id TEXT PRIMARY KEY NOT NULL;**
Error: near "CHANGE": syntax error
sqlite> alter table sex_type drop sex_id;
Error: near "DROP": syntax error
Always with the same supposed syntax error. About the only thing that has worked tonight:
sqlite> alter table sex_type RENAME TO gender;
sqlite> alter table gender_id RENAME TO sex_type;
So what is this syntax error that I'm overlooking, because going by my books my syntax should be fine. Do I have to insert something into these columns before modification can be done (which admittedly, I haven't tried yet)? Or am I missing something obvious about the ALTER/MODIFY/CHANGE/DROP command(s)?
SQLite's support for ALTER TABLE is pretty limited, including only RENAME TO and ADD_COLUMN. You're getting syntax errors because you're issuing a command that's not supported.
If you don't have any data to lose, you might be better of dropping and recreating the table.
If you do have data to lose, you might be better off renaming the table and creating a replacement using INSERT with SELECT, as seen in this example.

Resources