I would like to check in the table "PRENOTAZIONE" that the number of adults "n_adulti" is greater than 0 and less than max number of adults "n_max_adulti" in table "APPARTAMENTO".
This is the table PRENOTAZIONE
create table PRENOTAZIONE (
id_prenotazione serial,
data_inizio date not null,
data_fine date not null,
n_adulti smallint default 1,
n_bimbi smallint default 0,
n_neonati smallint default 0,
n_ospiti_extra smallint default 0,
appartamento integer not null,
cliente varchar(255),
primary key(id_prenotazione),
foreign key (appartamento)
references APPARTAMENTO(id_appartamento),
foreign key (cliente)
references CLIENTE(email)
);
and this is the table APPARTAMENTO
create table APPARTAMENTO (
id_appartamento serial,
sconti_mensili real default 0,
sconti_settimanali real default 0,
n_camere_letto smallint default 0,
n_letti smallint default 0,
n_posti_letto smallint default 0,
n_bagni smallint default 0,
orario_check_in time not null,
orario_check_out time not null,
n_max_bimbi smallint not null,
n_max_neonati smallint not null,
n_max_adulti smallint not null,
tipo varchar(255) not null,
descrizione varchar(100) default ' ',
ospiti_extra smallint default 0,
cauzione real default 0,
costi_pulizia real default 0,
costo_bimbo real default 0,
costo_adulto real default 0,
servizio varchar(255),
indirizzo integer,
proprietario varchar(255),
tipologia integer,
termine_cancellazione smallint default 1,
primary key(id_appartamento),
foreign key (indirizzo)
references INDIRIZZO(id_indirizzo),
foreign key (termine_cancellazione)
references TERMINE_DI_CANCELLAZIONE(id_termine),
foreign key (proprietario)
references PROPRIETARIO(email),
foreign key (tipologia)
references TIPOLOGIA_APPARTAMENTO(id_tipologia),
foreign key (servizio)
references SERVIZIO(servizio)
);
and this is the check operation i want to do
check ((n_adulti > 0) and (n_adulti <= (select n_max_adulti from APPARTAMENTO join PRENOTAZIONE on (id_appartamento = appartamento))))
and ((n_bimbi >= 0) and (n_bimbi <= (select n_max_bimbi from APPARTAMENTO join PRENOTAZIONE on (id_appartamento = appartamento))
and ((n_neonati > 0) and (n_neonati <= (select n_max_neonati from APPARTAMENTO join PRENOTAZIONE on (id_appartamento = appartamento)))))
but in PostgreSQL unfortunatly the sub query are not supported... and i need to do this with a trigger.
I looked something here: https://www.postgresql.org/docs/9.1/static/sql-createtrigger.html
and
https://www.tutorialspoint.com/postgresql/postgresql_triggers.htm
but i didn't find what i looking for...
I didn't understand how functions and triggers work together and how can I do this function.
PS: I'm sorry for the name of the tables but I'm Italian. However this database is a school project inspired by Airbnb.
The purpose was to create a similar and simplified database compared to Airbnb.
Create a trigger BEFORE INSERT OR UPDATE ON prenotazione FOR EACH ROW that calls the following PL/pgSQL trigger function:
Selects n_max_bimbi, n_max_neonati and n_max_adulti from the appartamento row that belongs to NEW.appartamento.
If NEW.n_adulti is not between 0 and the n_max_adulti found above, raise an appropriate exception. Similar for the others.
Related
I am currently trying to convert a postgres query to be compatible with Snowflake and work the same way.
Postgres
CREATE SEQUENCE IF NOT EXISTS public.etl_jobs_delta_loading_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
CREATE TABLE IF NOT EXISTS public.etl_jobs_delta_loading
(
id INTEGER DEFAULT nextval('public.etl_jobs_delta_loading_id_seq'::regclass) NOT NULL,
job_name VARCHAR(500) NOT NULL,
loaded_until TIMESTAMP,
etl_execution_time TIMESTAMP,
execution_status VARCHAR(30)
);
I translated the sequence to Snowflake, but keep getting errors while trying to get the nextVal in snowflake.
Snowflake
CREATE OR REPLACE SEQUENCE etl_jobs_delta_loading_id_seq
START = 1
INCREMENT = 1
CREATE TABLE IF NOT EXISTS public.etl_jobs_delta_loading
(
id INTEGER DEFAULT nextval('public.etl_jobs_delta_loading_id_seq'::regclass) NOT NULL, -- statement that needs to be converted
job_name VARCHAR(500) NOT NULL,
loaded_until TIMESTAMP,
etl_execution_time TIMESTAMP,
execution_status VARCHAR(30)
);
I have tried various approaches on creating the etl_jobs_delta_loading table but no luck till now. Any ideas on how to implement this in snowflake?
The correct syntax to get value from sequence is <seq_name>.NEXTVAL:
CREATE OR REPLACE SEQUENCE PUBLIC.etl_jobs_delta_loading_id_seq
START = 1
INCREMENT = 1;
CREATE TABLE IF NOT EXISTS public.etl_jobs_delta_loading
(
id INTEGER DEFAULT public.etl_jobs_delta_loading_id_seq.NEXTVAL NOT NULL,
job_name VARCHAR(500) NOT NULL,
loaded_until TIMESTAMP,
etl_execution_time TIMESTAMP,
execution_status VARCHAR(30)
);
Related: Sequences as Expressions
Alternatively using IDENTITY/AUTOINCREMENT property:
CREATE OR REPLACE TABLE public.etl_jobs_delta_loading
(
id INTEGER NOT NULL IDENTITY(1,1),
job_name VARCHAR(500) NOT NULL,
loaded_until TIMESTAMP,
etl_execution_time TIMESTAMP,
execution_status VARCHAR(30)
);
I have a table that is already created with data and I need only modify the schema to add some constraints .
my created tabled schema
CREATE TABLE public.note (
note_id bigint NOT NULL,
confidential boolean NOT NULL,
follow_up_date date,
notification_date date,
priority integer NOT NULL,
recurring_follow_up_interval interval,
status character varying(255) NOT NULL,
create_date timestamp with time zone,
deleted boolean NOT NULL,
last_modified_date timestamp with time zone,
time_spent integer,
title text,
version bigint NOT NULL,
assigned_to_id bigint,
note_category_id bigint NOT NULL,
created_by_id bigint,
last_modified_by_id bigint
);
what I need to match
create table note
(
note_id bigint default nextval('note_id_seq'::regclass) not null,
confidential boolean not null,
follow_up_date date,
notification_date date,
priority integer default 0 not null,
recurring_follow_up_interval interval,
status varchar(255) not null,
create_date timestamp with time zone,
deleted boolean default false not null,
last_modified_date timestamp with time zone,
time_spent integer,
title text,
version bigint default 0 not null,
assigned_to_id bigint,
note_category_id bigint not null,
created_by_id bigint,
last_modified_by_id bigint,
constraint note_pkey
primary key (note_id),
constraint fk_4nrhbn2j8j2vqqh78vleef9xr
foreign key (created_by_id) references admin_user,
constraint fk_eid7x7jfvjoe1h5tnyouhmqpa
foreign key (assigned_to_id) references admin_user,
constraint fk_oi5l4dg3sg5ep5neagmvp9r7o
foreign key (note_category_id) references note_category,
constraint fk_tk8ncyc0hmdi3gfh67b4jyu3l
foreign key (last_modified_by_id) references admin_user
);
as you can see it missing all defaults + all constraint to the other tables
any way to copy the intended schema to the created one without loosing the data
I am using Postgres 12
UPDATE
I know I could use alter to modify some columns but it will be a long process for me as there are many columns and I got more than 300 tables that have the same case
I manually alter one column to add sequence but I need easier way to do that for all columns
ALTER TABLE ONLY note ALTER COLUMN note_id SET DEFAULT nextval('note_id_seq'::regclass);
In postgresql I have a table which I need to add a new column. the original table ddl is belowing:
CREATE TABLE survey.survey_response (
id uuid NOT NULL DEFAULT uuid_generate_v4(),
survey_id uuid NOT NULL,
survey_question_id uuid NULL,
user_id varchar(256) NULL,
device_id varchar(256) NULL,
user_country varchar(100) NULL,
client_type varchar(100) NULL,
product_version varchar(100) NULL,
answer text NULL,
response_date timestamptz NOT NULL DEFAULT now(),
survey_category varchar(100) NULL,
tags varchar(250) NULL,
tracking_id uuid NULL,
CONSTRAINT survey_response_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
) ;
Then I alter the table to add a new column:
alter table survey.survey_response add column system_tags varchar(30) ;
But after that I found my instert statement cannot make change to this new column, for all the original columns it works fine:
INSERT INTO survey.survey_response
(id, survey_id, user_id, tags, system_tags)
VALUES(uuid_generate_v4(), uuid_generate_v4(),'1123','dsfsd', 'dsfsd');
select * from survey.survey_response where user_id = '1123';
The "tags" columns contains inserted value, however, system_tags keeps null.
I tested the above scenario in my local postgreSQL 9.6, any ideas about this strange behavior? Thanks a lot
-----------------update----------
I found this survey.survey_response table has been partitioning based on month, So my inserted record will also be displayed in survey.survey_response_y2017m12. but the new system_tags column is also NULL
CREATE TABLE survey.survey_response_y2017m12 (
id uuid NOT NULL DEFAULT uuid_generate_v4(),
survey_id uuid NOT NULL,
survey_question_id uuid NULL,
user_id varchar(256) NULL,
device_id varchar(256) NULL,
user_country varchar(100) NULL,
client_type varchar(100) NULL,
product_version varchar(100) NULL,
answer text NULL,
response_date timestamptz NOT NULL DEFAULT now(),
survey_category varchar(100) NULL,
tags varchar(250) NULL,
tracking_id uuid NULL,
system_tags varchar(30) NULL,
CONSTRAINT survey_response_y2017m12_response_date_check CHECK (((response_date >= '2017-12-01'::date) AND (response_date < '2018-01-01'::date)))
)
INHERITS (survey.survey_response)
WITH (
OIDS=FALSE
) ;
If I run the same scenario in a non-partition table then the insert works fine.
So do I need any special settings for alter table for partition table?
Old thread but you need to drop and create again the RULE to fix the issue.
I am completely new in Postgres commands.
I have the following DB2 commands to create tables and table spaces:
CREATE USER TEMPORARY TABLESPACE MYSPACE MANAGED BY AUTOMATIC STORAGE#
CREATE TABLESPACE SYSTOOLSPACE MANAGED BY AUTOMATIC STORAGE#
CREATE SEQUENCE REVISION AS BIGINT START WITH 1 INCREMENT BY 1 MAXVALUE 4611686018427387903 CYCLE CACHE 1000#
Now i want to run these commands in postgresql , I have tried with
my_db=# CREATE USER TEMPORARY TABLESPACE MYSPACE MANAGED BY AUTOMATIC STORAGE;
ERROR: syntax error at or near "TABLESPACE"
LINE 1: CREATE USER TEMPORARY TABLESPACE MYSPACE MANAGED BY AUTO...
my_db=# CREATE TABLESPACE SYSTOOLSPACE MANAGED BY AUTOMATIC STORAGE;
ERROR: syntax error at or near "MANAGED"
LINE 1: CREATE TABLESPACE SYSTOOLSPACE MANAGED BY AUTOMATIC STORAGE;
I also have this DB2 CREATE TABLE statement:
CREATE TABLE USER (
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1 INCREMENT BY 1 NO MAXVALUE NO CYCLE CACHE 100),
E_VER BIGINT NOT NULL,
NAME VARCHAR(38) NOT NULL UNIQUE,
EMAIL_ADDRESS VARCHAR(255) NOT NULL,
PASSWORD VARCHAR(32) NOT NULL,
SUPER_ADMIN SMALLINT NOT NULL,
MAIN_ADMIN SMALLINT NOT NULL,
SERVER_ADMIN SMALLINT NOT NULL,
GROUP_ADMIN SMALLINT NOT NULL,
CLIENT_ADMIN SMALLINT NOT NULL,
ENABLED SMALLINT NOT NULL,
HIDDEN SMALLINT NOT NULL,
PRIMARY KEY (ID)
)#
and I have tried to convert this to Postgres:
CREATE SEQUENCE USER_seq START WITH 1 INCREMENT BY 1;
CREATE TABLE USER (
ID BIGINT DEFAULT NEXTVAL ('USER_seq'),
E_VER BIGINT NOT NULL,
NAME VARCHAR(38) NOT NULL UNIQUE,
EMAIL_ADDRESS VARCHAR(255) NOT NULL,
PASSWORD VARCHAR(32) NOT NULL,
SUPER_ADMIN SMALLINT NOT NULL,
MAIN_ADMIN SMALLINT NOT NULL,
SERVER_ADMIN SMALLINT NOT NULL,
GROUP_ADMIN SMALLINT NOT NULL,
CLIENT_ADMIN SMALLINT NOT NULL,
ENABLED SMALLINT NOT NULL,
HIDDEN SMALLINT NOT NULL,
PRIMARY KEY (ID)
)#
by http://www.sqlines.com/online this online site. After running this command i am getting error like
my_db=# CREATE SEQUENCE USER_seq START WITH 1 INCREMENT BY 1;
CREATE SEQUENCE
my_db=#
my_db=#
my_db=# CREATE TABLE USER (
my_db(# ID BIGINT DEFAULT NEXTVAL ('USER_seq'),
my_db(# E_VER BIGINT NOT NULL,
my_db(# NAME VARCHAR(38) NOT NULL UNIQUE,
my_db(# EMAIL_ADDRESS VARCHAR(255) NOT NULL,
my_db(# PASSWORD VARCHAR(32) NOT NULL,
my_db(# SUPER_ADMIN SMALLINT NOT NULL,
my_db(# MAIN_ADMIN SMALLINT NOT NULL,
my_db(# SERVER_ADMIN SMALLINT NOT NULL,
my_db(# GROUP_ADMIN SMALLINT NOT NULL,
my_db(# CLIENT_ADMIN SMALLINT NOT NULL,
my_db(# ENABLED SMALLINT NOT NULL,
my_db(# HIDDEN SMALLINT NOT NULL,
my_db(# PRIMARY KEY (ID)
my_db(# );
ERROR: syntax error at or near "USER"
LINE 1: CREATE TABLE USER (
^
Anything wrong this conversion? Any suggestion solve this error?
USER is a reserved word, you need to escape it as CREATE TABLE "USER".
As for your CREATE USER and CREATE TABLESPACE commands, that's just wrong syntax. There's no MANAGED BY in Postgres for example.
Using Postgres, what I would like to achieve is to be able to have many different instrument types, with corresponding [TYPE].instrument tables, which all have a unique ID in the table, but also reference a unique ID in the instrument.master table. I have the following:
create schema instrument
CREATE TABLE instrument.type (
id smallserial NOT NULL,
name text not null,
code text not null,
CONSTRAINT pk_instrument_type PRIMARY KEY (id)
);
ALTER TABLE instrument.type ADD CONSTRAINT unq_instrument_type_code UNIQUE(code);
ALTER TABLE instrument.type ADD CONSTRAINT unq_instrument_type_name UNIQUE(name);
insert into instrument.type (name, code) values ('futures', 'f');
CREATE TABLE instrument.master (
id serial NOT NULL,
type smallint not null references instrument.type (id),
timestamp timestamp with time zone not null,
CONSTRAINT pk_instrument_master PRIMARY KEY (id)
);
CREATE TABLE futures.definition (
id smallserial NOT NULL,
code text not null,
CONSTRAINT pk_futures_definition PRIMARY KEY (id)
);
ALTER TABLE futures.definition ADD CONSTRAINT unq_futures_definition_code UNIQUE(code);
insert into futures.definition (code) values ('ED');
CREATE TABLE futures.instrument (
id smallserial NOT NULL,
master serial not null references instrument.master (id),
definition smallint not null references futures.definition (id),
month smallint not null,
year smallint not null,
CONSTRAINT pk_futures_instrument PRIMARY KEY (id),
check (month >= 1),
check (month <= 12),
check (year >= 1900)
);
ALTER TABLE futures.instrument ADD CONSTRAINT unq_futures_instrument UNIQUE(definition, month, year);
CREATE OR REPLACE FUNCTION trigger_master_futures()
RETURNS trigger AS
$BODY$
BEGIN
insert into instrument.master (type, timestamp)
select id, current_timestamp from instrument.type where code = 'f';
NEW.master := currval('instrument.master_id_seq');
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
create trigger trg_futures_instrument before insert on futures.instrument
for each row
execute procedure trigger_master_futures();
I then test with:
insert into futures.instrument (definition, month, year)
select id, 3, 2015 from futures.definition where code = 'ED';
Everything works almost as I would like it to. The only issue is that somehow, instrument.master.id ends up being one more than futures.instrument.master. I am not sure what I need to do to achieve the behavior I want, which is that whenever an entry is inserted into futures.instrument, an entry should be inserted into instrument.master, and the id entry of the latter should be inserted into the master entry of the former. I actually think it should have failed since the foreign key relationship is violated somehow.
As it turns out, everything was correct. The issue was that in futures.instrument, the type of the master column is serial, and it should have been int.