"0"|"0"|"0"|"2"|"10"|"1.000"
"1"|"1"|"1"|"2"|"14"|"2.000"
"2"|"2"|"3"|"5"|"16"|"4.000"
-"3"|"0"|"2"|"3"|"11"|"1.000"
+"3"|"0"|"2"|"2"|"11"|"1.000"
"ID"|"PRODUIT"|"CONSO"|"QUANTITÉ"
-"1"|"0"|"2"|"1.000"
+"2"|"31"|"3"|"23.000"
"2"|"2025-04-10 00:00:00"|"2"|
"3"|"2025-04-14 00:00:00"|"0"|
"4"|"2025-04-14 00:00:00"|"1"|
-"5"|"2025-04-08 00:00:00"|"0"|
--- /dev/null
+"ID"|"DATE"|"PRODUIT"|"EUROS"
+"0"|"2025-04-01 00:00:00"|"0"|"42.00"
+"1"|"2025-04-01 00:00:00"|"1"|"2.00"
+"2"|"2025-04-01 00:00:00"|"2"|"4.00"
+"3"|"2025-04-01 00:00:00"|"3"|"89.00"
+"4"|"2025-04-01 00:00:00"|"4"|"8.00"
+"5"|"2025-04-01 00:00:00"|"5"|"7.00"
+"6"|"2025-04-01 00:00:00"|"6"|"39.00"
+"7"|"2025-04-17 00:00:00"|"0"|"32.00"
+"8"|"2025-04-26 00:00:00"|"2"|"84.00"
+"9"|"2025-04-28 00:00:00"|"0"|"23.00"
+"10"|"2025-04-29 00:00:00"|"0"|"23.00"
"ID"|"PRODUIT"|"QUANTITÉ"|"PANIER"
"0"|"10"|"1.000"|"0"
"1"|"14"|"2.000"|"1"
-"2"|"16"|"4.000"|"2"
-"3"|"10"|"1.000"|"3"
-"4"|"14"|"2.000"|"4"
-"5"|"11"|"1.000"|"5"
+"2"|"11"|"1.000"|"0"
+"3"|"16"|"4.000"|"2"
+"4"|"10"|"1.000"|"3"
+"5"|"14"|"2.000"|"4"
+"6"|"11"|"1.000"|"3"
#odbcinst -q -d -n SQLite3
#odbcinst -q -s -h
#odbcinst -q -s -n ${database}
+ nix build -o hsqldb ${pkgs.hsqldb}
set +x
echo "You may now launch runServer"
'' # + checks.${system}.git-hooks-check.shellHook
-server.database.0=file:LesQuatreRoux;default_schema=true;default_table_type=cached;shutdown=false;sql.lowercase_ident=true
+server.database.0=file:LesQuatreRoux;default_schema=true;default_table_type=cached;shutdown=false;get_column_name=false;sql.lowercase_ident=true
server.dbname.0=LesQuatreRoux
-server.database.1=file:Test;default_schema=true;shutdown=false;default_table_type=cached;get_column_name=false;sql.lowercase_ident=true
-server.dbname.1=test
--- /dev/null
+\p SYSTEM_PRIMARYKEYS
+SELECT * FROM INFORMATION_SCHEMA.SYSTEM_PRIMARYKEYS;
+
+--\p SYSTEM_TABLES
+--SELECT TABLE_NAME FROM INFORMATION_SCHEMA.SYSTEM_TABLES;
+
+\p SYSTEM_CROSSREFERENCE
+SELECT * FROM INFORMATION_SCHEMA.SYSTEM_CROSSREFERENCE;
--- /dev/null
+\.
+--TRUNCATE TABLE "Vente";
+--TRUNCATE TABLE "Panier";
+DROP PROCEDURE insertVente IF EXISTS CASCADE;
+CREATE PROCEDURE insertVente
+ ( IN venteDate DATE
+ , IN venteClient INTEGER
+ , IN venteProduit INTEGER
+ , IN venteQuantité DECIMAL
+ )
+ MODIFIES SQL DATA
+ BEGIN ATOMIC
+ DECLARE panierID INTEGER DEFAULT NULL;
+ DECLARE venteID INTEGER DEFAULT NULL;
+
+ -- CorrectnessNote: seule la date et le client
+ -- font partie des critères pour décider
+ -- si le panier existe déjà où non.
+ SET panierID = SELECT ID FROM "Panier"
+ WHERE "Panier".date = venteDate
+ AND "Panier".client = venteClient;
+ IF panierID IS NULL
+ THEN
+ INSERT INTO "Panier"(date, client)
+ VALUES (venteDate, venteClient);
+ SET panierID = IDENTITY();
+ END IF;
+
+ -- CorrectnessNote: la quantité ne fait pas partie des critères
+ -- pour décider si la vente existe déjà ou non.
+ SET venteID = SELECT ID FROM "Vente"
+ WHERE "Vente".panier = panierID
+ AND "Vente".produit = venteProduit;
+ IF venteID IS NULL
+ THEN
+ INSERT INTO "Vente"(panier, produit, quantité)
+ VALUES (panierID, venteProduit, venteQuantité);
+ END IF;
+ END
+.;
+
+DROP PROCEDURE insertVentesParAbonnement IF EXISTS;
+CREATE PROCEDURE insertVentesParAbonnement(IN finalDate DATE)
+ MODIFIES SQL DATA
+ BEGIN ATOMIC
+ -- ExplanationNote: gère chaque jour l'un après l'autre.
+ for_days:
+ FOR SELECT day
+ FROM UNNEST (SEQUENCE_ARRAY(DATE '2025-04-07', finalDate, 1 DAY))
+ WITH ORDINALITY as T(day, I)
+ DO
+ -- ExplanationNote: pour un jour donné,
+ -- gère chaque abonnement l'un après l'autre.
+ for_abos:
+ FOR SELECT ID as aboID
+ , client as aboClient
+ , produit as aboProduit
+ , quantité as aboQuantité
+ , période as aboP
+ FROM "Abonnement"
+ JOIN "Période" ON "Période".ID = "Abonnement".période
+ AND "Période".nom = DAYNAME(day)
+ DO
+ CALL insertVente(day, aboClient, aboProduit, aboQuantité);
+ END FOR for_abos;
+ END FOR for_days;
+ END;
+.;
+
+CALL insertVentesParAbonnement(DATE '2025-04-07' + 7 DAY);
+
+\i sql/show.sql
+
+--call prix_à_date(CURRENT_DATE);
+select "Prod".nom_complet, date, euros
+from table (prix_à_date(CURRENT_DATE)) as PD
+join table (choisirUnProduit()) as "Prod" ON "Prod".ID = produit
+;
\xq SELECT * FROM "Panier"
* *DSV_TARGET_FILE = data/Vente.csv
\xq SELECT * FROM "Vente"
+* *DSV_TARGET_FILE = data/Prix.csv
+\xq SELECT * FROM "Prix"
* *DSV_TARGET_TABLE = "Facture"
\mq data/Facture.csv
-\p Importing Panier
-* *DSV_TARGET_TABLE = "Panier"
-\mq data/Panier.csv
+--\p Importing Panier
+--* *DSV_TARGET_TABLE = "Panier"
+--\mq data/Panier.csv
\p Importing Produit
* *DSV_TARGET_TABLE = "Produit"
\p Importing Ingrédient
* *DSV_TARGET_TABLE = "Ingrédient"
\mq data/Ingrédient.csv
+
+\p Importing Prix
+* *DSV_TARGET_TABLE = "Prix"
+\mq data/Prix.csv
ALTER SCHEMA PUBLIC RENAME TO B;
\c false
SET DATABASE COLLATION "French";
-\p CREATE TABLE tmp
-DROP TABLE tmp IF EXISTS;
-CREATE TABLE tmp (ID INT);
-INSERT INTO tmp(ID) VALUES (0);
+SET DATABASE DEFAULT TABLE TYPE CACHED;
+--\p CREATE TABLE tmp
+--DROP TABLE tmp IF EXISTS;
+--CREATE TABLE tmp (ID INT);
+--INSERT INTO tmp(ID) VALUES (0);
\i sql/init/Produit.sql
\i sql/init/Ingrédient.sql
\i sql/init/Panier.sql
\i sql/init/Vente.sql
\i sql/init/Stock.sql
+\i sql/init/Prix.sql
, produit INTEGER NOT NULL
, quantité DECIMAL(100,3) DEFAULT 1.000 NOT NULL
, CONSTRAINT "PK_Abonnement" PRIMARY KEY(ID)
- , CONSTRAINT "FK_Abonnement_client" FOREIGN KEY(client) REFERENCES "Client"(ID) ON DELETE CASCADE
+ , CONSTRAINT "FK_Abonnement_client"
+ FOREIGN KEY(client)
+ REFERENCES "Client"(ID)
+ ON DELETE CASCADE
+ , CONSTRAINT "FK_Abonnement_produit"
+ FOREIGN KEY(produit)
+ REFERENCES "Produit"(ID)
+ ON UPDATE CASCADE
+ , CONSTRAINT "FK_Abonnement_période"
+ FOREIGN KEY(période)
+ REFERENCES "Période"(ID)
+ ON UPDATE CASCADE
+ , CONSTRAINT "FK_Abonnement_lieu"
+ FOREIGN KEY(lieu)
+ REFERENCES "Lieu"(ID)
+ ON UPDATE CASCADE
);
-ALTER TABLE "Abonnement"
- ADD CONSTRAINT "FK_Abonnement_produit" FOREIGN KEY(produit) REFERENCES "Produit"(ID)
- ON UPDATE CASCADE;
-ALTER TABLE "Abonnement"
- ADD CONSTRAINT "FK_Abonnement_période" FOREIGN KEY(période) REFERENCES "Période"(ID)
- ON UPDATE CASCADE;
-ALTER TABLE "Abonnement"
- ADD CONSTRAINT "FK_Abonnement_lieu" FOREIGN KEY(lieu) REFERENCES "Lieu"(ID)
- ON UPDATE CASCADE;
ALTER TABLE "Client"
ADD CONSTRAINT "FK_Client_lieu" FOREIGN KEY(lieu) REFERENCES "Lieu"(ID)
ON UPDATE CASCADE;
+
+DROP FUNCTION choisirUnClient IF EXISTS CASCADE;
+CREATE FUNCTION choisirUnClient()
+ RETURNS TABLE(nom_complet VARCHAR(100), ID INTEGER)
+ READS SQL DATA
+ BEGIN ATOMIC
+ RETURN TABLE
+ (SELECT nom || ' (' || "Lieu".nom || ')' AS nom_complet
+ , ID
+ FROM "Client"
+ JOIN "Lieu" ON "Lieu".ID = "Client".lieu
+ );
+ END;
+.;
\p CREATE TABLE Facture
CREATE CACHED TABLE "Facture"
( ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL
- , date INTEGER NOT NULL
+ , date DATE DEFAULT CURRENT_DATE NOT NULL
, CONSTRAINT "PK_Facture" PRIMARY KEY(ID)
);
, conso INTEGER NOT NULL
, quantité DECIMAL(100,3) DEFAULT 1.000 NOT NULL
, CONSTRAINT "PK_Ingrédient" PRIMARY KEY(ID)
+ , CONSTRAINT "Un produit ne se liste pas lui-même comme consommation"
+ CHECK (produit != conso)
+ , CONSTRAINT "FK_Ingrédient_produit"
+ FOREIGN KEY(produit)
+ REFERENCES "Produit"(ID)
+ ON UPDATE CASCADE
+ , CONSTRAINT "FK_Ingrédient_conso"
+ FOREIGN KEY(conso)
+ REFERENCES "Produit"(ID)
+ ON UPDATE CASCADE
);
CREATE UNIQUE INDEX "Ingrédient_index_produit_et_conso"
ON "Ingrédient"(produit,conso);
-ALTER TABLE "Ingrédient"
- ADD CONSTRAINT "Un produit ne se liste pas lui-même comme consommation"
- CHECK (produit != conso)
-ALTER TABLE "Ingrédient" ADD CONSTRAINT "FK_Ingrédient_produit" FOREIGN KEY(produit) REFERENCES "Produit"(ID)
- ON UPDATE CASCADE;
-ALTER TABLE "Ingrédient" ADD CONSTRAINT "FK_Ingrédient_conso" FOREIGN KEY(conso) REFERENCES "Produit"(ID)
- ON UPDATE CASCADE;
\p CREATE TABLE Panier
CREATE CACHED TABLE "Panier"
( ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL
- , date DATE NOT NULL
+ , date DATE DEFAULT CURRENT_DATE NOT NULL
, client INTEGER NOT NULL
, facture INTEGER
, CONSTRAINT "PK_Panier" PRIMARY KEY(ID)
+ , CONSTRAINT "FK_Panier_facture"
+ FOREIGN KEY(facture)
+ REFERENCES "Facture"(ID)
+ ON UPDATE CASCADE
+ , CONSTRAINT "FK_Panier_client"
+ FOREIGN KEY(client)
+ REFERENCES "Client"(ID)
+ ON UPDATE CASCADE
);
-ALTER TABLE "Panier"
- ADD CONSTRAINT "FK_Panier_facture" FOREIGN KEY(facture) REFERENCES "Facture"(ID)
- ON UPDATE CASCADE;
-ALTER TABLE "Panier"
- ADD CONSTRAINT "FK_Panier_client" FOREIGN KEY(client) REFERENCES "Client"(ID)
- ON UPDATE CASCADE;
--- /dev/null
+\p CREATE TABLE Prix
+CREATE CACHED TABLE "Prix"
+ ( ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL
+ , date DATE DEFAULT CURRENT_DATE NOT NULL
+ , produit INTEGER NOT NULL
+ , euros DECIMAL(100,2) DEFAULT 0.00 NOT NULL
+ , CONSTRAINT "PK_Prix" PRIMARY KEY(ID)
+ , CONSTRAINT "FK_Prix_produit"
+ FOREIGN KEY(produit)
+ REFERENCES "Produit"(ID)
+ ON UPDATE CASCADE
+ , CONSTRAINT "La combinaison (produit, date) d'un prix doit être unique"
+ UNIQUE (produit, date)
+ );
+
+DROP FUNCTION produit_maxdate IF EXISTS CASCADE;
+CREATE FUNCTION produit_maxdate(IN at_date DATE)
+ RETURNS TABLE(produit INTEGER, max_date DATE)
+ READS SQL DATA
+ BEGIN ATOMIC
+ RETURN TABLE
+ (SELECT "Produit".ID as produit
+ , MAX( date ) as max_date
+ FROM "Prix"
+ JOIN "Produit" ON "Produit".ID = "Prix".produit
+ WHERE date <= at_date
+ GROUP BY "Produit".ID
+ );
+ END;
+.;
+
+DROP FUNCTION prix_à_date IF EXISTS CASCADE;
+CREATE FUNCTION prix_à_date(IN at_date DATE)
+ RETURNS TABLE(produit INTEGER, "DATE" DATE, euros DECIMAL)
+ READS SQL DATA
+ BEGIN ATOMIC
+ RETURN TABLE
+ (SELECT produit, date, euros
+ FROM TABLE (produit_maxdate(at_date)) as P
+ JOIN "Prix" ON "Prix".produit = P.produit
+ AND "Prix".date = P.max_date
+ );
+ END;
+.;
, quantité DECIMAL(100,3) DEFAULT 1.000 NOT NULL
, conditionnement VARCHAR(100)
, CONSTRAINT "PK_Produit" PRIMARY KEY(ID)
+ , CONSTRAINT "La combinaison (nom, quantité, conditionnement) d'un produit doit être unique"
+ UNIQUE (nom, quantité, conditionnement)
);
+
+DROP FUNCTION choisirUnProduit IF EXISTS CASCADE;
+CREATE FUNCTION choisirUnProduit()
+ RETURNS TABLE(nom_complet VARCHAR(100), ID INTEGER)
+ READS SQL DATA
+ BEGIN ATOMIC
+ RETURN TABLE
+ (SELECT nom || ' ('
+ || RTRIM(RTRIM(TO_CHAR(quantité),'0'),'.')
+ || nvl(unité,'')
+ || ')'
+ AS nom_complet
+ , ID
+ FROM "Produit"
+ );
+ END;
+.;
, produit INTEGER NOT NULL
, quantité DECIMAL(100,3) DEFAULT 1.000 NOT NULL
, CONSTRAINT "PK_Stock" PRIMARY KEY(ID)
+ , CONSTRAINT "FK_Stock_lieu"
+ FOREIGN KEY(lieu)
+ REFERENCES "Lieu"(ID)
+ ON UPDATE CASCADE
+ , CONSTRAINT "FK_Stock_produit"
+ FOREIGN KEY(produit)
+ REFERENCES "Produit"(ID)
+ ON UPDATE CASCADE
);
-ALTER TABLE "Stock"
- ADD CONSTRAINT "FK_Stock_lieu" FOREIGN KEY(lieu) REFERENCES "Lieu"(ID)
- ON UPDATE CASCADE;
-ALTER TABLE "Stock"
- ADD CONSTRAINT "FK_Stock_produit" FOREIGN KEY(produit) REFERENCES "Produit"(ID)
- ON UPDATE CASCADE;
, quantité DECIMAL(100,3) DEFAULT 1.000 NOT NULL
, panier INTEGER NOT NULL
, CONSTRAINT "PK_Vente" PRIMARY KEY(ID)
+ , CONSTRAINT "FK_Vente_produit"
+ FOREIGN KEY(produit)
+ REFERENCES "Produit"(ID)
+ ON UPDATE CASCADE
+ , CONSTRAINT "FK_Vente_panier"
+ FOREIGN KEY(panier)
+ REFERENCES "Panier"(ID)
+ ON UPDATE CASCADE
);
-ALTER TABLE "Vente"
- ADD CONSTRAINT "FK_Vente_produit" FOREIGN KEY(produit) REFERENCES "Produit"(ID)
- ON UPDATE CASCADE;
-ALTER TABLE "Vente"
- ADD CONSTRAINT "FK_Vente_panier" FOREIGN KEY(panier) REFERENCES "Panier"(ID)
- ON UPDATE CASCADE;
--- /dev/null
+NEXT_DAY(CURRENT_DATE, 'WEDNESDAY')
+DROP TYPE SYS_REFCURSOR CASCADE;
+CREATE TYPE SYS_REFCURSOR AS INT;
+
+SET DATABASE REFERENTIAL INTEGRITY FALSE;
+SET DATABASE REFERENTIAL INTEGRITY TRUE;
+SELECT * FROM UNNEST(SEQUENCE_ARRAY(CURRENT_DATE, CURRENT_DATE + 6 DAY, 1 DAY)) WITH ORDINALITY AS T(D, I);
+
+CREATE FUNCTION an_hour_before (t TIMESTAMP)
+ RETURNS TIMESTAMP
+ RETURN t - 1 HOUR
+
+CREATE PROCEDURE delete_extra_customers(INOUT val_p INT, IN lastname_p VARCHAR(20))
+ MODIFIES SQL DATA
+ BEGIN ATOMIC
+ SET val_p = 0;
+ for_label: FOR SELECT * FROM customers WHERE lastname = lastname_p DO
+ IF val_p > 0 THEN
+ DELETE FROM customers WHERE customers.id = id;
+ END IF;
+ SET val_p = val_p + 1;
+ END FOR for_label;
+ END
+
+-- DECLARE my_ver INTEGER DEFAULT 2;
+-- loop_label: WHILE my_var < 20 DO
+-- INSERT INTO CUSTOMERS VALUES (DEFAULT, my_var);
+-- SET my_var = my_var + 1;
+-- -- LEAVE can be used to break the loop
+-- IF my_var = 15 THEN LEAVE loop_label; END IF;
+-- END WHILE loop_label;
+
+-- Array of dates
+SELECT *
+FROM UNNEST(SEQUENCE_ARRAY(DATE '2025-04-07', CURRENT_DATE + 7 DAY, 1 DAY))
+ WITH ORDINALITY AS T(D, I);
+DECLARE LOCAL NAMES TABLE test_retval (x INT);
+
+
+
+
+
+CREATE TABLE customers(id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, firstname VARCHAR(50), lastname VARCHAR(50), added TIMESTAMP);
+
+CREATE TABLE addresses(id INTEGER GENERATED BY DEFAULT AS IDENTITY, customerid INTEGER, address VARCHAR(50));
+
+ALTER TABLE addresses ADD CONSTRAINT fk_addr FOREIGN KEY(customerid) REFERENCES customers(id);
+
+\.
+DROP PROCEDURE new_customer IF EXISTS;
+CREATE PROCEDURE new_customer(firstname VARCHAR(50), lastname VARCHAR(50))
+ MODIFIES SQL DATA DYNAMIC RESULT SETS 1
+ BEGIN ATOMIC
+ DECLARE result CURSOR FOR SELECT * FROM CUSTOMERS WHERE ID = IDENTITY();
+ INSERT INTO CUSTOMERS VALUES (DEFAULT, firstname, lastname, CURRENT_TIMESTAMP);
+ OPEN result;
+ END
+.;
+
+--CREATE VIEW Prix
+--CREATE DOMAIN valid_string AS VARCHAR(20) DEFAULT 'NO VALUE' CHECK (VALUE IS NOT NULL AND CHARACTER_LENGTH(VALUE) > 2)
+--select "Prix".*, P.*
+-- FROM TABLE (produit_maxdate(CURRENT_DATE)) as P
+-- JOIN "Prix" ON "Prix".ID = P.ID
+-- AND "Prix".date = P.max_date
+--;
+-- SELECT "PRICES".*
+-- FROM ( SELECT "PID", MAX( "D" ) AS "MD"
+-- FROM "PRICES" JOIN "PROD" ON "PROD"."ID" = "PRICES"."PID"
+-- WHERE "EX" = FALSE AND "D" <= COALESCE ( :pDate, CURRENT_DATE )
+-- GROUP BY "PID" ) AS "X"
+-- JOIN "PRICES" ON "PRICES"."PID" = "X"."PID"
+-- AND "PRICES"."D" = "X"."MD"
+
+--SET retval = SEQUENCE_ARRAY(DATE '2025-04-07', DATE '2025-04-17', 1 DAY);
+--select count(*) from information_schema.columns where table_name='LOB_IDS' and table_schema='SYSTEM_LOBS';
--- /dev/null
+
+
+You can create recursive procedures following the same guidelines. First create the procedure with a simple body that throws an exception. You need to specify the SPECIFIC name of the procedure:
+
+CREATE PROCEDURE updateFolderTotals(IN p_id VARCHAR(32), IN p_size BIGINT, IN p_files INT, IN p_folders INT)
+ SPECIFIC updateFolderTotals_1 MODIFIES SQL DATA
+ SIGNAL SQLSTATE '45000'
+
+Then alter the created procedure with the full body:
+
+ALTER SPECIFIC ROUTINE updateFolderTotals_1
+ BEGIN ATOMIC
+ DECLARE l_parentid VARCHAR(32);
+ UPDATE folders
+ SET tot_files = tot_files + p_files,
+ tot_size = tot_size + p_size ,
+ tot_folders = tot_folders + p_folders
+ WHERE id = p_id;
+
+ SELECT parentid INTO l_parentid FROM folders WHERE id = p_id;
+
+ IF (l_parentid IS NOT NULL) THEN
+ CALL updateFolderTotals(l_parentid,p_size,p_files,p_folders);
+ END IF;
+END;
+
+
--- /dev/null
+\p Table Abonnement
+SELECT ID as abonnement_id,
+ "Client".nom as client_nom,
+ "Lieu".nom as lieu_nom,
+ "Période".nom as période_nom,
+ "Produit".nom as produit_nom,
+ quantité
+ FROM "Abonnement"
+ JOIN "Client" ON "Client".ID = client
+ JOIN "Lieu" ON "Lieu".ID = lieu
+ JOIN "Période" ON "Période".ID = période
+ JOIN "Produit" ON "Produit".ID = produit;
+\p .
+\p Table Panier
+SELECT ID as panier_id,
+ TO_CHAR(date, 'YYYY-MM-DD') as panier_date,
+ "Client".nom as panier_client_nom,
+ "Lieu".nom as panier_lieu_nom
+ FROM "Panier"
+ JOIN "Client" ON "Client".ID = client
+ JOIN "Lieu" ON "Lieu".ID = "Client".lieu
+ ;
+\p .
+\p Table Vente
+SELECT ID as vente_id,
+ "Panier".ID as panier_id,
+ TO_CHAR("Panier".date, 'YYYY-MM-DD') as vente_panier_date,
+ "Client".nom as vente_panier_client_nom,
+ "Produit".nom as vente_produit,
+ "Vente".quantité as vente_quantité
+ FROM "Vente"
+ JOIN "Panier" ON "Panier".ID = panier
+ JOIN "Produit" ON "Produit".ID = produit
+ JOIN "Client" ON "Client".ID = client
+ ;
+\p .
+\p Table Prix
+SELECT ID as prix_id,
+ TO_CHAR("Prix".date, 'YYYY-MM-DD') as prix_date,
+ "Produit".nom as prix_produit,
+ euros as prix_euros
+ FROM "Prix"
+ JOIN "Produit" ON "Produit".ID = produit
+ ;