sqlite3 unique on multiple criteria - sqlite

I'm trying to create a table in sqlite3 that will store user field selections and make each combination of user_id, table, and name_id unique. However running the following gets me "ERROR: near "table": syntax error"
CREATE TABLE preftest (
'id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
'user_id' INTEGER NOT NULL,
'table' TEXT NOT NULL,
'name_id' INTEGER NOT NULL,
CONSTRAINT userpref UNIQUE(user_id, table, name_id))
Is there some issue with combining text and integer columns in a unique constraint?

table is a SQLite keyword.
You need to use 'table' instead of table in the constraint:
CREATE TABLE preftest (
'id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
'user_id' INTEGER NOT NULL,
'table' TEXT NOT NULL,
'name_id' INTEGER NOT NULL,
CONSTRAINT userpref UNIQUE(user_id, 'table', name_id))

Related

How to configure periods dynamically according to number of persons?

I'm making a database for my expense tracker/splitter (offers possibility to add/edit/remove Transactions). Depending on number of Persons, when you add a new transaction you must specify who paid and to what amount. Then it creates Payments row for each person within Transactions.
You must configure each person's salary then it will calculate the pro-rata for each person for unpaid expenses (IsPayed flag). Once every person is ready to settle they must create a period (start and end date). All transactions between those dates will be tagged as paid (IsPayed = true) and the application will assume they are settle and frozen in time. There will be a FK between Transaction and Period to specify from which period a transaction was paid.
I want to add a relation between Period(Id) and SalaryConfiguration(IdGroup); it would specify SalaryConfiguration for said period, but I can't since IdGroup is not a primary key. I do not know how a period can be dynamic on the number of persons and specific configurations. How can I link SalaryConfiguration and Periods?
Database DDL:
CREATE TABLE "Transactions" (
"Id" INTEGER NOT NULL UNIQUE,
"FkIdCategories" INTEGER NOT NULL,
"Date" TEXT NOT NULL,
"Name" TEXT NOT NULL,
"Description" TEXT,
"Cost" INTEGER NOT NULL,
"IsPayed" INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY("Id" AUTOINCREMENT),
CONSTRAINT "Fk_Categories_Transactions" FOREIGN KEY("FkIdCategories") REFERENCES "Categories"("Id")
);
CREATE TABLE "Categories" (
"Id" INTEGER NOT NULL UNIQUE,
"Name" TEXT NOT NULL UNIQUE,
PRIMARY KEY("Id" AUTOINCREMENT)
);
CREATE TABLE "Payments" (
"Id" INTEGER NOT NULL UNIQUE,
"FkIdPerson" INTEGER NOT NULL,
"FkIdTransaction" INTEGER NOT NULL,
"Amount" INTEGER NOT NULL,
CONSTRAINT "Fk_Persons_Payments" FOREIGN KEY("FkIdPerson") REFERENCES "Persons"("Id"),
CONSTRAINT "Fk_Transactions_Payments" FOREIGN KEY("FkIdTransaction") REFERENCES "Transactions"("Id"),
PRIMARY KEY("Id" AUTOINCREMENT)
);
CREATE TABLE "Persons" (
"Id" INTEGER NOT NULL UNIQUE,
"Name" TEXT NOT NULL,
PRIMARY KEY("Id" AUTOINCREMENT)
);
CREATE TABLE "SalaryConfigurations" (
"Id" INTEGER NOT NULL UNIQUE,
"IdGroup" INTEGER NOT NULL,
"FkIdPerson" INTEGER NOT NULL,
"Salary" INTEGER NOT NULL,
"SaveDate" TEXT NOT NULL,
CONSTRAINT "Fk_Persons_SalaryConfiguration" FOREIGN KEY("FkIdPerson") REFERENCES "Persons"("Id"),
PRIMARY KEY("Id" AUTOINCREMENT)
);
CREATE TABLE "Periods" (
"Id" INTEGER NOT NULL UNIQUE,
"StartDate" TEXT NOT NULL,
"EndDate" TEXT NOT NULL,
"FkIDSalaryConfigurationGroup" INTEGER NOT NULL,
PRIMARY KEY("Id" AUTOINCREMENT)
);
You can link the two tables together with another table that contains SalaryConfigurations(Id) and Periods(Id).

sqlite constraint base another table

I have 2 tables CarParking and ParkingArea. On ParkingArea I need to save the MaxPricePerDay, and on CarParking I have to save the cost. I try to write constraint that the cost is under or equal to MaxPricePerDay base on the AID columnn.
How can I do that?
CREATE TABLE "CarParking" (
"StartTime" TIMESTAMP NOT NULL,
"EndTime" TIMESTAMP NOT NULL,
"Cost" INTEGER NOT NULL,
"CID" INTEGER NOT NULL,
"AID" INTEGER NOT NULL,
FOREIGN KEY("CID") REFERENCES "Car"("CID")
ON DELETE CASCADE,
FOREIGN KEY("AID") REFERENCES "ParkingArea"("AID")
ON DELETE SET NULL,
CONSTRAINT time_car CHECK(StartTime<=EndTime),
PRIMARY KEY("StartTime","CID")
);
CREATE TABLE "ParkingArea" (
"MaxPricePerDay" INTEGER NOT NULL,
"PricePerHour" INTEGER NOT NULL,
"Name" TEXT NOT NULL,
"AID" INTEGER UNIQUE NOT NULL,
"Neighborhood" INTEGER NOT NULL,
PRIMARY KEY("AID"),
FOREIGN KEY ("Neighborhood") REFERENCES "Neighborhood" ("NID")
ON DELETE CASCADE
);
Since CHECK constraints can't have subqueries, one way is using a trigger instead.
CREATE TRIGGER check_max_price BEFORE INSERT ON CarParking
BEGIN
SELECT raise(ABORT, 'Exceeded MaxPricePerDay')
FROM ParkingArea
WHERE aid = new.aid AND new.Cost > MaxPricePerDay;
END;
is a starting point; you'll have to tweak the calculation to see if the cost is too much as appropriate.
If your cost can be updated after a row is inserted, you'll want a similar trigger for UPDATE.

SQL Error Regarding Foreign Key Restraint

I am currently getting the following error when trying to add to one of my tables:
Error adding record: FOREIGN KEY constraint failed: (INSERT INTO Stock(StockID,ItemName,MinAmountRequired,AmountInStock,Order? (Yes/No),DataLastUpdated,OrderNumber,SupplierRefrence,PurchaseID`) VALUES (1,",0,0,",",0,0,0);)
Currently, This is how I have my tables set up:
Stock
CREATE TABLE Stock (
StockID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
ItemName TEXT NOT NULL,
MinAmountRequired INTEGER NOT NULL,
AmountInStock INTEGER NOT NULL,
Order? (Yes/No) TEXT NOT NULL,
DataLastUpdated TEXT NOT NULL,
OrderNumber INTEGER NOT NULL UNIQUE,
SupplierReference INTEGER NOT NULL,
PurchaseID INTEGER NOT NULL UNIQUE,
FOREIGN KEY(PurchaseID) REFERENCES Purchase(PurchaseID),
FOREIGN KEY(OrderNumber) REFERENCES Orders(OrderNumber),
FOREIGN KEY(SupplierReference) REFERENCES Supplier(SupplierReference));
Orders
CREATE TABLE Orders (
OrderNumber INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
CustomerReferenceNumber INTEGER NOT NULL UNIQUE,
OrderDate TEXT NOT NULL,
ItemName TEXT NOT NULL UNIQUE);
Suppliers
CREATE TABLE Supplier (
SupplierReference INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
Name TEXT NOT NULL UNIQUE,
Address TEXT NOT NULL UNIQUE,
ContactNumber INTEGER NOT NULL UNIQUE);
Purchases
CREATE TABLE Purchase (
PurchaseID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
Date TEXT NOT NULL,
AmountSpent REAL NOT NULL);
You have defined these foreign keys in table Stock:
FOREIGN KEY(PurchaseID) REFERENCES Purchase(PurchaseID),
FOREIGN KEY(OrderNumber) REFERENCES Orders(OrderNumber),
FOREIGN KEY(SupplierReference) REFERENCES Supplier(SupplierReference)
meaning that the values in columns PurchaseID, OrderNumber, SupplierReference need to reference values in columns of the tables Purchase, Orders and Supplier.
But you want to store 0 to all of these columns which I'm sure that is not the value of any of the referenced columns, since these referenced columns are defined as
PRIMARY KEY AUTOINCREMENT
and so their values are > 0.
Pass valid values that do exist in these 3 tables and the statement will execute succesfully.

Recursive foreign key 'on delete cascade'

CREATE TABLE IF NOT EXISTS type (
tid INTEGER NOT NULL,
uuid VARCHAR NOT NULL,
name VARCHAR NOT NULL,
CONSTRAINT PK PRIMARY KEY (tid),
CONSTRAINT UNQ_0 UNIQUE (uuid),
CONSTRAINT UNQ_1 UNIQUE (name)
);
CREATE INDEX IDX_type_0 ON type (tid,uuid,name);
CREATE TABLE IF NOT EXISTS object (
oid VARCHAR NOT NULL,
timestamp VARCHAR NOT NULL,
tid INTEGER NOT NULL,
CONSTRAINT FK_tid FOREIGN KEY (tid) REFERENCES type(tid) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT UNQ_0 UNIQUE (oid)
);
CREATE INDEX IDX_object_0 ON object (oid,timestamp,tid);
CREATE TABLE IF NOT EXISTS object_user_owner (
uid INTEGER NOT NULL,
oid VARCHAR NOT NULL,
CONSTRAINT FK_uid FOREIGN KEY (uid) REFERENCES user(uid) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT FK_oid FOREIGN KEY (oid) REFERENCES object(oid) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT UNQ_0 UNIQUE (oid,uid)
);
CREATE INDEX IDX_object_user_owner_0 ON object_user_owner (uid,oid);
CREATE TABLE IF NOT EXISTS user (
uid INTEGER NOT NULL,
uuid VARCHAR NOT NULL,
name VARCHAR NOT NULL,
password VARCHAR NOT NULL,
salt VARCHAR NOT NULL,
timestamp VARCHAR NOT NULL,
lastaccess VARCHAR NOT NULL,
CONSTRAINT PK PRIMARY KEY (uid),
CONSTRAINT UNQ_0 UNIQUE (uuid),
CONSTRAINT UNQ_1 UNIQUE (name)
);
CREATE INDEX IDX_user_0 ON user (uid,uuid,name);
The above three sqlite3 tables contain foreign keys. The problem is the deletion of a key in the upper table type. When I try do delete I get 'FOREIGN KEY constraint failed' Error. Deleting a from the lowest table object_user_owner before deleting a type works. I think sqlite does not check any recursive cascade constraints. Does anyone have experienced this too or is anything wrong with my design?

Drop Unique Key and generate new unique key

I have created one table in oracle data base my table script is
CREATE TABLE wsc_widget_bundle (
id VARCHAR (50),
widgetBundle BLOB NULL,
devicesoftwareclass VARCHAR(30) NOT NULL,
widgetProfileId VARCHAR (50) NOT NULL,
bundleHash BLOB NULL,
widgetLocale VARCHAR (6) NOT NULL ,
status INT,
primary key(id),
unique(widgetProfileId, devicesoftwareclass,status),
foreign key(widgetProfileId) references wsc_widget_profile(id)
);
When i create ddl for that is looks like
create table "DEV1"."WSC_WIDGET_BUNDLE"(
"ID" VARCHAR2(50) not null,
"WIDGETBUNDLE" BLOB,
"DEVICESOFTWARECLASS" VARCHAR2(30) not null,
"WIDGETPROFILEID" VARCHAR2(50) not null,
"BUNDLEHASH" BLOB,
"WIDGETLOCALE" VARCHAR2(6) not null,
"STATUS" NUMBER,
constraint "SYS_C00323290" primary key ("ID")
);
alter table "DEV1"."WSC_WIDGET_BUNDLE"
add constraint "SYS_C00323292"
foreign key ("WIDGETPROFILEID")
references "MTP440_DEV1"."WSC_WIDGET_PROFILE"("ID");
create unique index "MTP440_DEV1"."SYS_C00323290" on "MTP440_DEV1"."WSC_WIDGET_BUNDLE"("ID");
create unique index "MTP440_DEV1"."SYS_C00323291" on "MTP440_DEV1"."WSC_WIDGET_BUNDLE"("WIDGETPROFILEID","DEVICESOFTWARECLASS","STATUS");
create index "MTP440_DEV1"."TEST" on "MTP440_DEV1"."WSC_WIDGET_BUNDLE"("DEVICESOFTWARECLASS","STATUS","WIDGETLOCALE","WIDGETPROFILEID");
Now i want to write alter script to alter unique key constrain of my table but as at creation of table I didn't mention the name of my unique key name it is given by system like SYS_C00323291
So how can I write alter script to drop that unique key whose name is not known to me and generation new one
You can find the name of the constraint by querying the user_constraints and user_cons_columns views.
Alter table x
drop constraint pk;
Alter table x
add constraint New_constraint_name PRIMARY KEY (colname);

Resources