SQL library trigger - sql

Im trying to make a library database. I would like to ensure that one book can be borrowed just to one person at a time. I have no expirience with triggers so I thought I might ask you.
create table "book" (
"book_id" INTEGER not null,
"condition" VARCHAR2(50),
"isbn" VARCHAR2(50) not null,
constraint PK_BOOK primary key ("book_id")
);
create table "borrowed" (
"book_id" INTEGER not null,
"borrowed_id" INTEGER not null,
"user_id" INTEGER not null,
"date_borrowing" DATE not null,
"date_returning" DATE not null,
"returned" SMALLINT not null,
constraint PK_BORROWED primary key ("book_id", "borrowed_id")
);
atribute "returned" has just yes or no value (1 or 0)

You don't need a trigger for this. Your borrowed table should be structured like this. Note the use of a virtual column, which requires Oracle 11g+:
create table borrowed (
borrowed_id INTEGER not null primary key, -- this should be set to a unique id for each row, using your preferred method
book_id INTEGER not null,
user_id INTEGER not null,
date_borrowing DATE not null,
date_returning DATE not null,
date_actualreturn DATE,
returned as (case date_actualreturn is null then 0 else 1 end)
);
Then, you want date_actualreturn to have at most one NULL value per book. You can do this with a unique index or constraint:
create table borrowed (
borrowed_id INTEGER not null primary key, -- this should be set to a unique id for each row, using your preferred method
book_id INTEGER not null,
user_id INTEGER not null,
date_borrowing DATE not null,
date_returning DATE not null,
date_actualreturn DATE,
returned as (case date_actualreturn is null then 0 else 1 end),
constraint unq_only_one_book_borrowed unique
(coalesce(date_actualreturn, date '1900-01-01'), book_id)
);
This creates a unique constraint on the column. If a book has not been returned, the date always looks the same -- so the same book cannot be borrowed twice. And, voila! No trigger.

Related

How implement the function of `case` in DDL?

I have a table order. Its DDL is listed below
create table "order"
(
id serial primary key,
quantity integer not null,
estimated_delivery_date date not null,
lodgement_date date check ( lodgement_date > '2022-03-02' ),
product_model varchar(128) not null,
sales_id integer not null,
contract_number varchar(10) not null
);
I want to make the lodgement_date attribute to be null if it is later than 2022-03-02 when inserting a new row. How can I achieve this function in DDL.
To do that, you can't do it in the creation of the table. It is gonna be a constraint.
Example:
CONSTRAINT check_lodgement_date
CHECK (lodgement_date > '2022-03-02')

Oracle (ORA-02270) : no matching unique or primary key for that column list

I have two tables:
CREATE TABLE Trasy_srodki_transportu(
ID_Trasy Integer NOT NULL,
ID_pojazdu Integer NOT NULL
)
/
CREATE TABLE Trasy(
ID_Trasy Integer NOT NULL,
Linia Varchar2(4 ) NOT NULL,
Data_rozpoczecia_kursowania Date NOT NULL,
Data_zakonczenia_kursowania Date,
ID_Pracownika Integer NOT NULL
)
Now i want to add foreign key to Trasy_srodki_transportu referencing to Trasy table:
ALTER TABLE Trasy_srodki_transportu ADD CONSTRAINT Trasa_jest_wykorzystywana FOREIGN KEY (ID_Trasy) REFERENCES Trasy (ID_Trasy)
/
and this throws Oracle (ORA-02270) : no matching unique or primary key for this column-list error. Any suggestions how to fix this?Data modeler view
A foreign key needs to reference a key on the related table, but it's not the case in your example. Change the definition of the second table by adding a PRIMARY KEY constraint in it, as in:
CREATE TABLE Trasy (
ID_Trasy Integer PRIMARY KEY NOT NULL,
Linia Varchar2(4 ) NOT NULL,
Data_rozpoczecia_kursowania Date NOT NULL,
Data_zakonczenia_kursowania Date,
ID_Pracownika Integer NOT NULL
)
Alternatively, you can create a unique constraint on it, that can also serve as a key. For example:
CREATE TABLE Trasy (
ID_Trasy Integer NOT NULL,
Linia Varchar2(4 ) NOT NULL,
Data_rozpoczecia_kursowania Date NOT NULL,
Data_zakonczenia_kursowania Date,
ID_Pracownika Integer NOT NULL,
CONSTRAINT uq_idtrasy UNIQUE (ID_Trasy)
)

How should I structure my simple database?

I am creating a database (for data from an online game) in which I need to store Players and their Villages. Each Player has at least 1 village. All Villages are unique and every Village has exactly 1 owner(Player).
It is probably important to mention, that I intend to create a new table/tables every day since the online game in question releases an updated game world data file once every 24hours. Once a table is created, I will never have to make changes in it, I will only need to read data from it.
I came up with 2 solutions for now, but I dont know what the right approach is.
Solution1:
CREATE TYPE village_t AS (
id INTEGER,
x INTEGER,
y INTEGER,
village_id INTEGER,
village_name VARCHAR,
pop INTEGER,
region VARCHAR
);
CREATE TABLE players (
tribe INTEGER NOT NULL,
user_id INTEGER PRIMARY KEY,
user_name VARCHAR(30) UNIQUE NOT NULL,
aliance_id INTEGER NOT NULL,
aliance_name VARCHAR(30) NOT NULL,
villages village_t[]
);
Solution2:
CREATE TABLE players (
tribe INTEGER NOT NULL,
user_id INTEGER PRIMARY KEY,
user_name VARCHAR(30) UNIQUE NOT NULL,
aliance_id INTEGER NOT NULL,
aliance_name VARCHAR(30) NOT NULL
);
CREATE TABLE villages (
id INTEGER NOT NULL,
x INTEGER NOT NULL,
y INTEGER NOT NULL,
village_id INTEGER NOT NULL,
village_name VARCHAR NOT NULL,
user_id INTEGER,
CONSTRAINT fk_con FOREIGN KEY(user_id) REFERENCES players(user_id),
pop INTEGER NOT NULL,
region VARCHAR
);
CREATE INDEX idx ON villages(user_id);
You have a 1-n relationship. Each village ("n") has one owner ("1"). Your second solution is the canonical way of storing this information in a database.
Your first solution does not even enforce the notion that a village as one owner, so I'm not sure why you are considering it. The second imposes this condition as part of the data model.
Your second solution has set up the recommend foreign key and indexes for what you describe, by the way, so it looks fine.
If you need to read village data frequently, Solution 1 is not recommended. This is because the list of village ids design removes the scope of joining the person and village table
Solution 2 is the most preferred way of going about as it keeps all your options open (whether you would frequently need village data or not)
Another way of going about solution 2 is to create a cross-reference table for user_id and village_id
CREATE TABLE players (
tribe INTEGER NOT NULL,
user_id INTEGER PRIMARY KEY,
user_name VARCHAR(30) UNIQUE NOT NULL,
aliance_id INTEGER NOT NULL,
aliance_name VARCHAR(30) NOT NULL
);
CREATE TABLE villages (
id INTEGER NOT NULL,
x INTEGER NOT NULL,
y INTEGER NOT NULL,
village_id INTEGER NOT NULL,
village_name VARCHAR NOT NULL,
pop INTEGER NOT NULL,
region VARCHAR
);
CREATE TABLE xref_players_villages (
user_id INTEGER,
CONSTRAINT fk_con1 FOREIGN KEY(user_id) REFERENCES players(user_id),
village_id INTEGER,
CONSTRAINT fk_con2 FOREIGN KEY(village_id ) REFERENCES villages(village_id ),
);

conflicting NULL/NOT NULL declarations for column "id_bank_card" of table "bill"

I Got a table BILL which is associated to another table BANK_CARD as follows:
create table BILL (
id_bill BIGSERIAL not null,
id_bank_card BIGSERIAL null,
id_registred_user BIGSERIAL not null,
reference_number INT4 null,
purchase_date DATE null,
bill_status VARCHAR(50) null,
payment_method VARCHAR(50) null,
constraint PK_BILL primary key (id_bill)
);
create table BANK_CARD (
id_bank_card BIGSERIAL not null,
id_registred_user BIGSERIAL not null,
card_type VARCHAR(50) null,
card_number INT4 null,
expiring_date DATE null,
cipher INT4 null,
constraint PK_BANK_CARD primary key (id_bank_card)
);
The table BILL has a 0..1 association with the table BANK_CARD, and BANK_CARD has a 1..n association with table BILL.
But when i execute my sql script i get the following error:
conflicting NULL/NOT NULL declarations for column "id_bank_card" of table "bill"
Because the relationship BILL and BANK_CARD is 0..1 the foreign key id_bank_card can be null in the table bill, so i don't understand why i get this error.
Any help please?
Thanks.
You are confusing data type definitions for primary and foreign keys. A bigserial is a generator of values of the bigint type. The foreign keys should use that data type. See table definitions below. Also, use of the NULL clause is redundant as that is the default behaviour. Primary keys can not be NULL so NOT NULL there is also redundant.
create table bank_card (
id_bank_card bigserial,
id_registred_user bigint references <user table>,
card_type VARCHAR(50),
card_number INT4,
expiring_date DATE,
cipher INT4,
constraint PK_BANK_CARD primary key (id_bank_card)
);
create table bill (
id_bill BIGSERIAL,
id_bank_card bigint references bank_card,
id_registred_user bigint references <user table>,
reference_number INT4,
purchase_date DATE,
bill_status VARCHAR(50),
payment_method VARCHAR(50),
constraint pk_bill primary key (id_bill)
);
If you are using Java+PostgreSQL:
this can happen if you accidentially insert null strings into your statement.
String N = System.getProperty("line.seperator");
Returned null, screwing up my sql statement.
FIXES: (Choose One)
String N = System.lineSeparator();
String N = "\n";
Exact string as it appeared in my code:
String CT =(""
//:+"---------10--------20--------30-------39
//:+"0123456789012345678901234567890123456789
+"CREATE TABLE t_1( "+N//:0
+"id SERIAL PRIMARY KEY "+N//:30
+" ,c_1 INT "+N//:60
+" ,c_2 VARCHAR (255) "+N//:90
+" ,c_3 CHARACTER( 8 ) "+N//:120
+" ,c_4 BOOLEAN "+N//:150
+" ,c_5 BYTEA "+N//:180
+" ,c_6 DATE "+N//:210
+"); " //:240
);;
Exact Error Message when N==null instead of "\n":
org.postgresql.util.PSQLException:
ERROR: conflicting NULL/NOT NULL declarations
for column "nullid" of table "t_1"
Stack: Java+Heroku+Tomcat9+PostGreSQL 9.5.13

Creating Table (Oracle)

I am creating two tables. The first table creates with no errors, but when I try to create the SUBHEAD table, I get an error: Line 2, Missing right parenthesis. I am not sure what is wrong with this line. Below is my SQL statements:
CREATE TABLE HEAD
(Code NUMERIC(4,0) NOT NULL PRIMARY KEY,
HeadName VARCHAR(50) NOT NULL UNIQUE,
HType VARCHAR(1) NOT NULL,
HDate DATE NOT NULL,
OpBal DECIMAL(11,2) NOT NULL
);
CREATE TABLE SUBHEAD
(HCode NUMERIC(4,0) NOT NULL FOREIGN KEY REFERENCES HEAD(Code),
SubCode NUMERIC(4,0) NOT NULL,
SubName VARCHAR(50) NOT NULL,
SDate DATE NOT NULL,
OpBal DECIMAL (11,2) NOT NULL,
CONSTRAINT pk_subheadID PRIMARY KEY (HCode, SubCode)
);
syntax: http://docs.oracle.com/cd/B28359_01/server.111/b28286/clauses002.htm#SQLRF52167
note that "in-line" constraint syntax is : "col col_type REFERENCES TAB(COL)" and not "FOREIGN KEY"
The data type for number is NUMBER not NUMERIC
So my memory did not fool me - you can have multiple in-line constraints (although the syntax graph doesn't show it):
SQL> create table tt1(a number primary key);
Table created.
SQL> create table tt2(a number references tt1(a) not null);
Table created.
CREATE TABLE SUBHEAD
(HCode NUMERIC(4,0) NOT NULL, FOREIGN KEY (Hcode) REFERENCES HEAD(Code),
SubCode NUMERIC(4,0) NOT NULL,
SubName VARCHAR(50) NOT NULL,
SDate DATE NOT NULL,
OpBal DECIMAL (11,2) NOT NULL,
CONSTRAINT pk_subheadID PRIMARY KEY (HCode, SubCode)
);
(note comma, and reference to the new table column)