Block records from updating - postgresql

I have the following tables
tbl_orders
CREATE TABLE tbl_orders (
id integer NOT NULL,
customer_name character varying NOT NULL,
is_archived boolean NOT NULL
);
tbl_order_items
CREATE TABLE tbl_order_items (
id integer NOT NULL,
product_name character varying NOT NULL,
quantity integer NOT NULL,
order_id int NOT NULL
);
In my application I have the possibility to archive an order, which set the boolean isArchived to true to that order record. The order record can have multiple order items which I want to prevent from being updated when the order has the boolean isArchived set to true. Do I have to set an isArchived boolean on the order items level?
Is this possible to prevent this on database level?

You can create a BEFORE UPDATE trigger on tbl_order_items FOR EACH ROW that throws an error when the order NEW.order_id is archived.
That is the most elegant and normalized solution, but it requires that a trigger runs whenever a row in tbl_order_items is updated.

Related

A view that shows the name of the server, the id of the instance and the number of active sessions (a session is active if the end timestamp is null)

CREATE TABLE instances(
ser_name VARCHAR(20) NOT NULL,
id INTEGER NOT NULL ,
ser_ip VARCHAR(16) NOT NULL,
status VARCHAR(10) NOT NULL,
creation_ts TIMESTAMP,
CONSTRAINT instance_id PRIMARY KEY(id)
);
CREATE TABLE characters(
nickname VARCHAR(15) NOT NULL,
type VARCHAR(10) NOT NULL,
c_level INTEGER NOT NULL,
game_data VARCHAR(40) NOT NULL,
start_ts TIMESTAMP ,
end_ts TIMESTAMP NULL ,
player_ip VARCHAR(16) NOT NULL,
instance_id INTEGER NOT NULL,
player_username VARCHAR(15),
CONSTRAINT chara_nick PRIMARY KEY(nickname)
);
ALTER TABLE
instances ADD CONSTRAINT ins_ser_name FOREIGN KEY(ser_name) REFERENCES servers(name);
ALTER TABLE
instances ADD CONSTRAINT ins_ser_ip FOREIGN KEY(ser_ip) REFERENCES servers(ip);
ALTER TABLE
characters ADD CONSTRAINT chara_inst_id FOREIGN KEY(instance_id) REFERENCES instances(id);
ALTER TABLE
characters ADD CONSTRAINT chara_player_username FOREIGN KEY(player_username) REFERENCES players(username);
insert into instances values
('serverA','1','138.201.233.18','active','2020-10-20'),
('serverB','2','138.201.233.19','active','2020-10-20'),
('serverE','3','138.201.233.14','active','2020-10-20');
insert into characters values
('characterA','typeA','1','Game data of characterA','2020-07-18 02:12:12','2020-07-18 02:32:30','192.188.11.1','1','nabin123'),
('characterB','typeB','3','Game data of characterB','2020-07-19 02:10:12',null,'192.180.12.1','2','rabin123'),
('characterC','typeC','1','Game data of characterC','2020-07-18 02:12:12',null,'192.189.10.1','3','sabin123'),
('characterD','typeA','1','Game data of characterD','2020-07-18 02:12:12','2020-07-18 02:32:30','192.178.11.1','2','nabin123'),
('characterE','typeB','3','Game data of characterE','2020-07-19 02:10:12',null,'192.190.12.1','1','rabin123'),
('characterF','typeC','1','Game data of characterF','2020-07-18 02:12:12',null,'192.188.10.1','3','sabin123'),
('characterG','typeD','1','Game data of characterG','2020-07-18 02:12:12',null,'192.188.13.1','1','nabin123'),
('characterH','typeD','3','Game data of characterH','2020-07-19 02:10:12',null,'192.180.17.1','2','bipin123'),
('characterI','typeD','1','Game data of characterI','2020-07-18 02:12:12','2020-07-18 02:32:30','192.189.18.1','3','dhiraj123'),
('characterJ','typeD','3','Game data of characterJ','2020-07-18 02:12:12',null,'192.178.19.1','2','prabin123'),
('characterK','typeB','4','Game data of characterK','2020-07-19 02:10:12','2020-07-19 02:11:30','192.190.20.1','1','rabin123'),
('characterL','typeC','2','Game data of characterL','2020-07-18 02:12:12',null,'192.192.11.1','3','sabin123'),
('characterM','typeC','3','Game data of characterM','2020-07-18 02:12:12',null,'192.192.11.1','2','sabin123');
here I need a view that shows the name of the server, the id of the instance and the number of active sessions (a session is active if the end timestamp is null). do my code wrong or something else? i am starting to learn so hoping for positive best answers.
my view
create view active_sessions as
select i.ser_name, i.id, count(end_ts) as active
from instances i, characters c
where i.id=c.instance_id and c.end_ts = null
group by i.ser_name, i.id;
This does not do what you want:
where i.id = c.instance_id and c.end_ts = null
Nothing is equal to null. You need is null to check a value against null.
Also, count(end_ts) will always produce 0, as we know already that end_ts is null, which count() does not consider.
Finally, I would highly recommend using a standard join (with the on keyword), rather than an implicit join (with a comma in the from clause): this old syntax from decades ago should not be used in new code. I think that a left join is closer to what you want (it would also take in account instances that have no character at all).
So:
create view active_sessions as
select i.ser_name, i.id, count(c.nickname) as active
from instances i
left join characters c on i.id = c.instance_id and c.end_ts is null
group by i.ser_name, i.id;

MySQL Error 1136:Column count does not match value count at row 1?

CREATE TABLE IF NOT EXISTS actores(
id_actor INT NOT NULL,
nombre VARCHAR(45) NOT NULL,
nacionalidad VARCHAR(45),
nombre_personaje VARCHAR(45),
PRIMARY KEY(id_actor)
)ENGINE=InnoDB;
INSERT INTO actores (nombre, nacionalidad)
VALUES ('Will smith' 'Americano');
You are missing a comma separating the values you want to insert.
VALUES ('Will smith', 'Americano');
You should change the definition for the field id_actor too to use auto-increment. Otherwise, you will need to specify an id for every insertion.
ALTER TABLE `actores`
CHANGE COLUMN `id_actor` `id_actor` INT(11) NOT NULL AUTO_INCREMENT ;

How to select last value insert in column ( like function LAST() for OracleDB)

I'm actually sutend and I'm setting up DB PostgreSQL for my AirsoftShop and some request on it. I need to find similar function as SELECT LAST(xx) FROM yy usable on SQL server and OracleDB i think. For return the last insert values in the column target by LAST().
I have this table :
CREATE TABLE munition.suivi_ammo (
type_ammo integer NOT NULL,
calibre integer NOT NULL,
event integer NOT NULL,
date_event date NOT NULL,
entrance integer NOT NULL,
exit integer NOT NULL,
inventory integer NOT NULL,
FOREIGN KEY (calibre) REFERENCES munition.index(numero),
FOREIGN KEY (event) REFERENCES munition.index(numero),
FOREIGN KEY (type_ammo) REFERENCES munition.index(numero)
);
and index for definition by number id :
CREATE TABLE munition.index (
numero integer NOT NULL,
definition text NOT NULL,
PRIMARY KEY (numero)
);
I want to select the last inventory insert in the table and calculate the current inventory according to the inflow and outflow made after my inventory
It's works when i do this type of request with specific date to be sure to only have the last one inventory, but I do not want to have to do it
SELECT index.definition,
Sum(suivi_ammo.inventory) + Sum(suivi_ammo.entrance) - Sum(suivi_ammo.exit) AS Stock
FROM munition.suivi_ammo
INNER JOIN munition.index ON suivi_ammo.type_ammo = index.numero
WHERE date_event < '03/05/2019' AND date_event >= '2019-04-10'
GROUP BY index.definition;
I also tried to used last_value() window function but doesn't work.
Thx !

design of table with checked column or column with reference to primary key which is updatable

I faced a problem when creating/designing tables in DB2.
I have two tables, table users and table countries created as shown bellow
create table users
(
firstname varchar(20) not null,
lastname varchar(20) not null,
gender char(1) not null check (gender in ('M','F')),
birthdate date not null,
country char(3) not null,
)
create table testing.countries
(
name varchar(60) not null,
code2 char(2) not null,
code3 char(3) not null
)
I want to have in a column country in table users a 3-char code of a country of origin and during insertion of data to be checked if it is valid (or better to say if it exists) from the list of countries which are stored in table countries.
Because DB2 doesn't support a subquery/subselect in a check option (which would be the best for me) then it looks like a candidate for a foreign key on column country in users referencing to a primary key on column code3 in countries. But in case there will be update of 3-char code of any country, it will be impossible to update it in simple way.
I know that the update of this will not be so often and can be done manually by first inserting new data to countries, then updating values in users and then deleting the old values in countries but unfortunately there will be more similar tables where data will have to be checked during insertion against another table and data in referenced table will be updated quite often and then the manual update is uncomfortable. And of course I want the data in users to be updated in case the update in countries will be done.
What I want to ask is how to solve this. I thought about some before or instead of trigger but BEFORE cannot be used to change data in other tables and INSTEAD OF is expecting UNTYPED VIEW not the TABLE
SQL0159N The statement references an object that identifies an unexpected
object type. Object: "COUNTRIES". Object type: "TABLE". Expected object type:
"UNTYPED VIEW". LINE NUMBER=2. SQLSTATE=42809`
Can you please advise me?
Thanks in advance
try Something like this:
create table testing.users
(
firstname varchar(20) not null,
lastname varchar(20) not null,
gender char(1) not null check (gender in ('M','F')),
birthdate date not null,
country char(3) not null
)
create table testing.countries
(
name varchar(60) not null,
code2 char(2) not null,
code3 char(3) not null
)
ALTER TABLE testing.users ADD CONSTRAINT testing.PK_Users PRIMARY KEY
(firstname, lastname);
ALTER TABLE testing.countries ADD CONSTRAINT testing.PK_Countries PRIMARY KEY
(code3);
ALTER TABLE testing.users ADD CONSTRAINT testing.FK_Users_Countries FOREIGN KEY
(country)
REFERENCES testing.users
(code3)
ON DELETE CASCADE;

How to insert value into a column with a default value? [PostgreSQL 9.1]

I have such table:
CREATE TABLE employee (
id INTEGER DEFAULT NEXTVAL('ids'::regclass) NOT NULL,
name CHARACTER VARYING NOT NULL,
employer INTEGER DEFAULT (-1)
);
And I want to insert sth into this table (I want to leave employer as default, -1):
INSERT INTO employee (name, id) VALUES('Doe', 2);
but my PostgreSQL 9.1 is complaining:
ERROR: insert or update on table "employee" violates foreign key constraint "FK_employer"
DETAIL: Key (employer)=(-1) is not present in table "employer".
I know that theres no employer with id = -1 but still, I want it that way. I want to set employer as -1 for this emplyee. Is it possible with postgreSQL?
Make the default null. Is it good?
employer INTEGER DEFAULT null