Remove Unique constraint on a column in sqlite database - sql

I am trying to remove a UNIQUE constraint on a column for sqlite but I do not have the name to remove the constraint. How can I find the name of the UNIQUE constraint name to remove it.
Below is the schema I see for the table I want to remove the constraint
UNIQUE (datasource_name)
sqlite> .schema datasources
CREATE TABLE "datasources" (
created_on DATETIME NOT NULL,
changed_on DATETIME NOT NULL,
id INTEGER NOT NULL,
datasource_name VARCHAR(255),
is_featured BOOLEAN,
is_hidden BOOLEAN,
description TEXT,
default_endpoint TEXT,
user_id INTEGER,
cluster_name VARCHAR(250),
created_by_fk INTEGER,
changed_by_fk INTEGER,
"offset" INTEGER,
cache_timeout INTEGER, perm VARCHAR(1000), filter_select_enabled BOOLEAN, params VARCHAR(1000),
PRIMARY KEY (id),
CHECK (is_featured IN (0, 1)),
CHECK (is_hidden IN (0, 1)),
FOREIGN KEY(created_by_fk) REFERENCES ab_user (id),
FOREIGN KEY(changed_by_fk) REFERENCES ab_user (id),
FOREIGN KEY(cluster_name) REFERENCES clusters (cluster_name),
UNIQUE (datasource_name),
FOREIGN KEY(user_id) REFERENCES ab_user (id)
);

SQLite only supports limited ALTER TABLE, so you can't remove the constaint using ALTER TABLE. What you can do to "drop" the column is to rename the table, create a new table with the same schema except for the UNIQUE constraint, and then insert all data into the new table. This procedure is documented in the Making Other Kinds Of Table Schema Changes section of ALTER TABLE documentation.

I just ran into this myself. An easy solution was using DB Browser for SQLite
It let me remove a unique constraint with just a checkbox in a gui.

PRAGMA foreign_keys=off;
BEGIN TRANSACTION;
ALTER TABLE table_name RENAME TO old_table;
CREATE TABLE table_name
(
column1 datatype [ NULL | NOT NULL ],
column2 datatype [ NULL | NOT NULL ],
...
);
INSERT INTO table_name SELECT * FROM old_table;
COMMIT;
PRAGMA foreign_keys=on;
Source: https://www.techonthenet.com/sqlite/unique.php

I was just working through this issue on a small database and found it easier to dump the data as SQL statements, it prints out your tables exactly as they are and also adds the INSERT INTO statements to rebuild the DB.
The .help terminal command shows:
.dump ?OBJECTS? Render database content as SQL
and prints the SQL to the terminal, you can update it in a TXT file. For once off changes and tidying this seems like a reasonable solution albeit a little inelegant

Related

Activate foreign key constraints error in dataGrip

I'm working with DataGrip and sqlite.
I have a table suppliers and another named products :
CREATE TABLE Suppliers (id INTEGER NOT NULL PRIMARY KEY,
nom TEXT,
siege_social TEXT);
CREATE TABLE Products (id INTEGER NOT NULL PRIMARY KEY,
nom TEXT,
prix REAL,
supplier INTEGER,
FOREIGN KEY (supplier) REFERENCES Suppliers(id)
);
I tried PRAGMA foreign_keys = ON; to activate the foreign keys constraint as my teacher do.
However when I try to insert a product while having the supplier table empty, I get no error :
INSERT INTO Products values (1, "Lunettes Cobra", 30, 1);
I expected this : FOREIGN KEY constraint failed
Do you know how I could make it raise an error for this ?
Thanks !
Executing pragma statement enables that setting only for currents session. Console and editor perform in different sessions.
Just go to advanced tab of the data source settings and set it there. It'll be applied for all sessions.
#forpas asked for the whole code so I deleted all the existing tables and used this code :
PRAGMA foreign_keys = ON;
CREATE TABLE Suppliers (id INTEGER NOT NULL PRIMARY KEY,
nom TEXT,
siege_social TEXT);
CREATE TABLE Products (id INTEGER NOT NULL PRIMARY KEY,
nom TEXT,
prix REAL,
supplier INTEGER,
FOREIGN KEY (supplier) REFERENCES Suppliers(id)
);
INSERT INTO Products values (2, "Lunettes Cobra", 30, 1);
And everything worked as expected.
[2021-05-23 12:02:26] [19] [SQLITE_CONSTRAINT_FOREIGNKEY] A foreign key constraint failed (FOREIGN KEY constraint failed)
#forpas was right again, the fact that I created the table before activating the foreign_keys was not the problem. I used 2 console, one for creating the table and another for inserting values. I only activated foreign_keys in the first one. I thought it was activated in the database but it's console related.

Postgres breaking null constraint on a serial column

I have a table that I create independently, the primary key is set with the serial type and a sequence applied to the table, but when I try to insert a value a NULL CONSTRAINT error is thrown and the return looks like null was passed, am I missing something in the INSERT statement?
SQL for table generation:
DROP TABLE IF EXISTS public."Team" CASCADE;
CREATE TABLE public."Team" (
"IdTeam" serial PRIMARY KEY,
name text NOT null,
CONSTRAINT "pKeyTeamUnique" UNIQUE ("IdTeam")
);
ALTER TABLE public."Team" OWNER TO postgres;
DROP SEQUENCE IF EXISTS public."Team_IdTeam_seq" CASCADE;
CREATE SEQUENCE public."Team_IdTeam_seq"
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public."Team_IdTeam_seq" OWNER TO postgres;
ALTER SEQUENCE public."Team_IdTeam_seq" OWNED BY public."Team"."IdTeam";
SQL for insert :
INSERT INTO public."Team" (name) values ('Manchester Untited');
The returning error:
ERROR: null value in column "IdTeam" violates not-null constraint
DETAIL: Failing row contains (null, Manchester Untited).
SQL state: 23502
I am baffled. Why are you trying to define your own sequence when the column is already defined as serial?
Second, a primary key constraint is already unique. There is no need for a separate unique constraint.
Third, quoting identifiers just makes the code harder to write and to read.
You can just do:
DROP TABLE IF EXISTS public.Team CASCADE;
CREATE TABLE public.Team (
IdTeam serial PRIMARY KEY,
name text NOT null
);
INSERT INTO public.Team (name)
VALUES ('Manchester Untited');
Dropping the sequence causes the default definition for the IdTeam column to be dropped. After recreating the sequence you will have to recreate the default definition.

SQL Integrity constraint-Parent key not found

I have looked over the internet and their solutions wont fix my problem, hence I'm asking for help here to check if there's mistakes in my coding.
I wanted to create a temporary table populated by other source tables and then implement it into the fact table. I have checked if the data type and the parameter is matching or the sequence of the keys but still it's giving me the error
"ORA-02291: integrity constraint (SYSTEM.SYS_C007167) violated -
parent key not found"
Fact Table:
CREATE TABLE DW_ITEMS7364 (
DW_ID int not null,
ManID char(5),
WHID char(5),
STKID char(5),
Profit number,
CONSTRAINT DW_ID PRIMARY KEY (DW_ID),
FOREIGN KEY(ManID) REFERENCES DW_MANUFACTURER7364,
FOREIGN KEY(WHID) REFERENCES DW_WAREHOUSE7364,
FOREIGN KEY(StkID) REFERENCES DW_STOCKITEM7364);
CREATE SEQUENCE seq_items7364 START WITH 101 increment by 1;
CREATE TRIGGER trg_items7364 BEFORE INSERT OR UPDATE ON DW_ITEMS7364
FOR EACH ROW
BEGIN
SELECT seq_items7364.NEXTVAL
INTO :new.DW_ID
FROM dual;
END;
Temporary Table:
CREATE TABLE TEMP_TAB7364 AS( SELECT m.ManID, w.WHID, s.STKID, (s.SellingPrice-s.PurchasePrice) AS "Profit"
FROM MANUFACTURER7364 m LEFT OUTER JOIN STOCKITEM7364 s ON s.ManID = m.ManID
RIGHT OUTER JOIN WAREHOUSE7364 w on s.WHID = w.WHID WHERE s.SELLINGPRICE IS NOT NULL AND s.PURCHASEPRICE IS NOT NULL
);
These are my source tables:
CREATE TABLE MANUFACTURER7364(
ManID char(5),
ManName varchar (25),
CityID char(5) NOT NULL,
PRIMARY KEY(ManID),
FOREIGN KEY(CityID) REFERENCES CITY7364);
CREATE TABLE WAREHOUSE7364(
WHID char(5),
MaxNoOfPallets number,
CostPerPallet number,
SecurityLevel char(1),
FreezerFacilities varchar(10),
QuarantineFacilities varchar(10),
CityID char(5) NOT NULL,
PRIMARY KEY(WHID),
FOREIGN KEY(CityID) REFERENCES CITY7364);
CREATE TABLE STOCKITEM7364(
StkID char(5),
StkName varchar(20),
SellingPrice number,
PurchasePrice number,
ManID char(5) NOT NULL,
WHID char(5) NOT NULL,
PRIMARY KEY(StkID),
FOREIGN KEY(ManID) REFERENCES MANUFACTURER7364,
FOREIGN KEY(WHID) REFERENCES WAREHOUSE7364);
As far as I can tell, nothing of what you posted raises that error.
Additional drawback is the way you chose to create foreign key constraints. If you don't name it, Oracle assigns the name itself and it looks the way you posted it: SYSTEM.SYS_C007167.
SQL> create table test
2 (id_dept number,
3 id_emp number,
4 foreign key (id_dept) references dept (deptno),
5 foreign key (id_emp) references emp (empno));
Table created.
SQL> select constraint_name from user_constraints where table_name = 'TEST';
CONSTRAINT_NAME
------------------------------
SYS_C008172
SYS_C008173
SQL>
When one of these fails, looking at its name you have no idea what went wrong, unless you investigate a little bit more:
SQL> select column_name from user_cons_columns where constraint_name = 'SYS_C008173';
COLUMN_NAME
-----------------------
ID_EMP
SQL>
But, if you name the constraint, it is way simpler:
SQL> create table test
2 (id_dept number,
3 id_emp number,
4 constraint fk_test_dept foreign key (id_dept) references dept (deptno),
5 constraint fk_test_emp foreign key (id_emp) references emp (empno));
Table created.
SQL> select constraint_name from user_constraints where table_name = 'TEST';
CONSTRAINT_NAME
------------------------------
FK_TEST_DEPT
FK_TEST_EMP
SQL>
Another major drawback one notices is what's written in front of the dot, here: SYSTEM.SYS_C007167. Yes, that would be SYSTEM. Shortly, don't do that. Leave SYS and SYSTEM alone; they are powerful, they are special. Why would you take the risk of destroying the database if you (un)intentionally do something hazardous? Create another user, grant required privileges and work in that schema.
If I understood you correctly, once you create that temp table (TEMP_TAB7364), its contents is transferred into the DW_ITEMS7364 and - doing so - you hit the error.
If that's so, what's the purpose of the temp table? Insert directly into the target table and save resources. Will it fail? Of course it will, unless you change the query. How? I don't know - make sure that you don't insert values that don't exist in any of three tables used for enforcing referential integrity.
Though, as you already have the temp table, if it isn't too large, a (relatively) quick & dirty way of finding out which row is responsible for the error can be found with a loop, such as
begin
for cur_r in (select col1, col2, ... from temp_table) loop
begin
insert into target (col1, col2, ...)
values (cur_r.col1, cur_r.col2, ...);
exception
when others then
dbms_output.put_line(sqlerrm ||': '|| cur_r.col1 ||', '||cur_r.col2);
end;
end loop;
end;
The inner BEGIN-END block is here to make sure that the PL/SQL code won't exit at the first error, but will display them all. Then review those values and find the reason that makes your query invalid.

how to move tables from public to other schema in Postgres

Postgres 9.1 database contains tables yksus1 .. ykssu9 in public schema. pgAdmin shows those definitions as in code below.
How to move those tables to firma1 schema ?
Other tables in firma1 schema have foreign key references to those table primay keys. Foreign key references to those tables are only from tables in firma1 schema.
Some of those tables contain data.
If tables is moved to firma1 schema, foreign key references shouuld also be updated to firma1.yksusn tables.
Table structures cannot changed.
It looks like primary key sequences are already in firma1 schema so those should not moved.
Version string PostgreSQL 9.1.2 on x86_64-unknown-linux-gnu, compiled by gcc-4.4.real (Debian 4.4.5-8) 4.4.5, 64-bit
CREATE TABLE yksus1
(
yksus character(10) NOT NULL DEFAULT ((nextval('firma1.yksus1_yksus_seq'::regclass))::text || '_'::text),
veebis ebool,
nimetus character(70),
"timestamp" character(14) DEFAULT to_char(now(), 'YYYYMMDDHH24MISS'::text),
username character(10) DEFAULT "current_user"(),
klient character(40),
superinden character(20),
telefon character(10),
aadress character(50),
tlnr character(15),
rus character(60),
CONSTRAINT yksus1_pkey PRIMARY KEY (yksus)
);
ALTER TABLE yksus1
OWNER TO mydb_owner;
CREATE TRIGGER yksus1_trig
BEFORE INSERT OR UPDATE OR DELETE
ON yksus1
FOR EACH STATEMENT
EXECUTE PROCEDURE setlastchange();
other tables are similar:
CREATE TABLE yksus2
(
yksus character(10) NOT NULL DEFAULT ((nextval('firma1.yksus2_yksus_seq'::regclass))::text || '_'::text),
nimetus character(70),
"timestamp" character(14) DEFAULT to_char(now(), 'YYYYMMDDHH24MISS'::text),
osakond character(10),
username character(10) DEFAULT "current_user"(),
klient character(40),
superinden character(20),
telefon character(10),
aadress character(50),
tlnr character(15),
rus character(60),
CONSTRAINT yksus2_pkey PRIMARY KEY (yksus),
CONSTRAINT yksus2_osakond_fkey FOREIGN KEY (osakond)
REFERENCES yksus2 (yksus) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION DEFERRABLE INITIALLY IMMEDIATE
);
ALTER TABLE yksus2
OWNER TO mydb_owner;
CREATE TRIGGER yksus2_trig
BEFORE INSERT OR UPDATE OR DELETE
ON yksus2
FOR EACH STATEMENT
EXECUTE PROCEDURE setlastchange();
ALTER TABLE yksus1
SET SCHEMA firma1;
More details in the manual: http://www.postgresql.org/docs/current/static/sql-altertable.html
Associated indexes, constraints, and sequences owned by table columns are moved as well.
Not sure about the trigger function though, but there is an equivalent ALTER FUNCTION .. SET SCHEMA ... as well.

Can these three SQLITE INSERTS be combinded or improved?

I have three tables:
CREATE TABLE "local" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , "serialNumber" TEXT, "location" TEXT)
CREATE TABLE "setups" ("id" INTEGER PRIMARY KEY NOT NULL ,"hold" TEXT,"mode" INTEGER,"setTemp" REAL,"maxSTemp" REAL,"minSTemp" REAL,"units" TEXT,"heat" INTEGER,"heatMode" INTEGER,"fanMode" INTEGER,"fan" INTEGER,"cool" INTEGER)
CREATE TABLE "data" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,"humidity" REAL,"time" INTEGER,"filtChng" INTEGER,"indoorTemp" REAL,"outdoorTemp" REAL, "setups_id" INTEGER, "local_id" INTEGER)
Everytime I get a new entry I execute:
INSERT INTO local ('serialNumber') SELECT 'XXXX' WHERE NOT EXISTS (SELECT * FROM local WHERE serialNumber='XXXX')"
INSERT INTO setups ('hold','mode','setTemp','maxSTemp','minSTemp','units','heat','heatMode','fanMode','fan','cool') SELECT '00',1,74.0,74.0,74.0,'F',1,1,1,1,1 WHERE NOT EXISTS (SELECT * FROM setups WHERE hold='00' AND mode=1 AND setTemp=74.0 AND maxSTemp=74.0 AND minSTemp=74.0 AND units='F' AND heat=1 AND heatMode=1 AND fanMode=1 AND fan=1 AND cool=1)
INSERT INTO data ('humidity','filtChng','time','indoorTemp','outdoorTemp',local_id,setups_id) SELECT 74.0,111111111,100,74.0,74.0,local.id,setups.id FROM local CROSS JOIN setups WHERE local.serialNumber='XXXX' AND setups.hold='00' AND setups.mode=1 AND setups.setTemp=74.0 AND setups.maxSTemp=74.0 AND setups.minSTemp=74.0 AND setups.units='F' AND setups.heat=1 AND setups.heatMode=1 AND setups.fanMode=1 AND setups.fan=1 AND setups.cool=1
What I am doing works, but seems slow and redundant/inefficient...
Well, you can remove the "where not exists" part from the "local" insert if you use a unique constraint on the "serialNumber" field. Be careful, this will throw a constraint violation instead of just not inserting the row. So be sure to handle that in the application.
And though I assume it is, be sure that checking for duplicates is really necessary in your app.