Files
Pivot/sql/installatie_pivot_26-27.sql
2026-10-14 13:34:37 +02:00

807 lines
38 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- =====================================================================
-- PIVOT 1.1.0 – VOLLEDIGE INSTALLATIE (schooljaar 2026-27)
--
-- Maakt in één keer aan:
-- 1. de centrale database `pivot` (Scholen, Gebruikers, rechten, Logs, Bugs)
-- 2. de school 'Scholengroep Antwerpen' (code: sg-antwerpen)
-- 3. de gebruiker Marijn (Administrator) wachtwoord: Binnenin10
-- 4. de database van die school `pivot_sg_antwerpen` (Toestellen, Leerlingen, ...)
--
-- Uitvoeren met: mysql -u <gebruiker> -p < installatie_pivot_26-27.sql
-- (of in MySQL Workbench / phpMyAdmin: dit bestand importeren)
--
-- ANDERE NAAM VOOR DE CENTRALE DATABASE (bv. pivot_test)?
-- Vervang `pivot` op BEIDE regels onder "1. Centrale database"
-- (CREATE DATABASE én USE) en zet dezelfde naam in config.ini
-- › [database] › centrale_database.
-- Het script stopt met een duidelijke melding als de gekozen database nog
-- oude tabellen bevat (bv. 'scholen' van de vorige versie).
-- =====================================================================
SET NAMES utf8mb4;
-- ---------------------------------------------------------------------
-- 1. Centrale database
-- ---------------------------------------------------------------------
CREATE DATABASE IF NOT EXISTS `pivot` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE `pivot`;
-- Veiligheidscontrole: stop als deze database nog OUDE tabellen met dezelfde naam bevat
-- (bv. 'scholen' van PIVOT 1.1.0). MySQL op Windows maakt geen onderscheid tussen
-- hoofdletters en kleine letters, dus 'Scholen' en 'scholen' zijn dezelfde tabel.
DROP PROCEDURE IF EXISTS pivot_controle_oude_tabellen;
DELIMITER //
CREATE PROCEDURE pivot_controle_oude_tabellen()
BEGIN
DECLARE oud TEXT;
SELECT GROUP_CONCAT(n.tabel SEPARATOR ', ') INTO oud
FROM (SELECT 'scholen' AS tabel, 'school_id' AS kolom UNION ALL
SELECT 'gebruikers', 'gebruiker_id' UNION ALL SELECT 'logs', 'log_id' UNION ALL
SELECT 'status', 'bugstatus_id' UNION ALL SELECT 'bugs', 'bug_id') n
WHERE EXISTS (SELECT 1 FROM information_schema.TABLES t
WHERE t.TABLE_SCHEMA = DATABASE() AND LOWER(t.TABLE_NAME) = n.tabel)
AND NOT EXISTS (SELECT 1 FROM information_schema.COLUMNS c
WHERE c.TABLE_SCHEMA = DATABASE() AND LOWER(c.TABLE_NAME) = n.tabel
AND LOWER(c.COLUMN_NAME) = n.kolom);
IF oud IS NOT NULL THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT =
'STOP: deze database bevat nog oude PIVOT-tabellen (scholen/gebruikers/logs/status/bugs). Kies een nieuwe, lege database.';
END IF;
END //
DELIMITER ;
CALL pivot_controle_oude_tabellen();
DROP PROCEDURE pivot_controle_oude_tabellen;
CREATE TABLE IF NOT EXISTS Scholen (
School_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Code VARCHAR(32) NOT NULL,
School_naam VARCHAR(255) NOT NULL,
Smartschool_platform_url VARCHAR(255) NULL,
Adres VARCHAR(255) NULL,
Instellingsnummer VARCHAR(20) NULL,
Informat_instellingsnummer VARCHAR(500) NULL,
Onderwijsniveau VARCHAR(20) NULL,
Domein VARCHAR(500) NOT NULL DEFAULT '',
Hostnamen VARCHAR(500) NOT NULL DEFAULT '',
Actief TINYINT NOT NULL DEFAULT 1,
Db_naam VARCHAR(128) NOT NULL,
Instellingen MEDIUMTEXT NULL,
Google_sleutel MEDIUMTEXT NULL,
Leerlingenaantal INT NULL,
Leerlingenaantal_sync DATETIME NULL,
Leerlingenaantal_detail TEXT NULL,
Bijgewerkt DATETIME(6) NULL,
Bijgewerkt_door VARCHAR(255) NULL,
UNIQUE KEY uq_scholen_code (Code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Veiligheidsgroepen (
Veiligheidsgroep TINYINT NOT NULL PRIMARY KEY,
Naam VARCHAR(50) NOT NULL,
Omschrijving VARCHAR(255) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Gebruikers (
Gebruiker_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Gebruikersnaam VARCHAR(100) NOT NULL,
Veiligheidsgroep TINYINT NOT NULL DEFAULT 2,
Passwoordhash VARCHAR(255) NULL,
Emailadres VARCHAR(255) NULL,
Last_login DATETIME NULL,
IP_laatste_login VARCHAR(45) NULL,
Laatste_school VARCHAR(32) NULL,
Actief TINYINT NOT NULL DEFAULT 1,
UNIQUE KEY uq_gebruikersnaam (Gebruikersnaam),
UNIQUE KEY uq_emailadres (Emailadres),
CONSTRAINT fk_gebruikers_groep FOREIGN KEY (Veiligheidsgroep)
REFERENCES Veiligheidsgroepen (Veiligheidsgroep)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Onderdelen (
Onderdeel_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Code VARCHAR(50) NOT NULL,
Naam VARCHAR(255) NOT NULL,
Categorie VARCHAR(50) NOT NULL,
Volgorde INT NOT NULL DEFAULT 0,
UNIQUE KEY uq_onderdeel_code (Code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Gebruiker_rechten (
Gebruiker_ID INT NOT NULL,
School_ID INT NOT NULL,
Onderdeel_ID INT NOT NULL,
Toegekend_op DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
Toegekend_door VARCHAR(100) NULL,
PRIMARY KEY (Gebruiker_ID, School_ID, Onderdeel_ID),
KEY idx_rechten_school (School_ID),
KEY idx_rechten_onderdeel (Onderdeel_ID),
CONSTRAINT fk_rechten_gebruiker FOREIGN KEY (Gebruiker_ID)
REFERENCES Gebruikers (Gebruiker_ID) ON DELETE CASCADE,
CONSTRAINT fk_rechten_school FOREIGN KEY (School_ID)
REFERENCES Scholen (School_ID) ON DELETE CASCADE,
CONSTRAINT fk_rechten_onderdeel FOREIGN KEY (Onderdeel_ID)
REFERENCES Onderdelen (Onderdeel_ID) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Handleidingen (
Handleiding_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Slug VARCHAR(100) NOT NULL,
Titel VARCHAR(200) NOT NULL,
Categorie VARCHAR(100) NULL,
Samenvatting VARCHAR(300) NULL,
Inhoud MEDIUMTEXT NULL,
Zichtbaar VARCHAR(10) NOT NULL DEFAULT 'iedereen',
Volgorde INT NOT NULL DEFAULT 0,
Gewijzigd_op DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
Gewijzigd_door VARCHAR(100) NULL,
UNIQUE KEY uq_handleiding_slug (Slug)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Handleidingen_versies (
Versie_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Handleiding_ID INT NOT NULL,
Titel VARCHAR(200) NOT NULL,
Inhoud MEDIUMTEXT NULL,
Opgeslagen_op DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
Door VARCHAR(100) NULL,
KEY idx_versie_handleiding (Handleiding_ID, Opgeslagen_op),
CONSTRAINT fk_versie_handleiding FOREIGN KEY (Handleiding_ID)
REFERENCES Handleidingen (Handleiding_ID) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Leerlingenaantal_tellingen (
Telling_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
School_ID INT NOT NULL,
Peildatum DATE NOT NULL,
Schooljaar VARCHAR(10) NOT NULL,
Aantal INT NOT NULL,
Detail TEXT NULL,
Opgevraagd_op DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
Door VARCHAR(100) NULL,
UNIQUE KEY uq_telling (School_ID, Peildatum),
KEY idx_telling_datum (Peildatum),
CONSTRAINT fk_telling_school FOREIGN KEY (School_ID)
REFERENCES Scholen (School_ID) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Personeelsaantal_tellingen (
Telling_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
School_ID INT NOT NULL,
Peildatum DATE NOT NULL,
Schooljaar VARCHAR(10) NOT NULL,
Aantal INT NOT NULL,
Detail TEXT NULL,
Opgevraagd_op DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
Door VARCHAR(100) NULL,
UNIQUE KEY uq_ptelling (School_ID, Peildatum),
KEY idx_ptelling_datum (Peildatum),
CONSTRAINT fk_ptelling_school FOREIGN KEY (School_ID)
REFERENCES Scholen (School_ID) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Personeelsaantal_huidig (
School_ID INT NOT NULL PRIMARY KEY,
Aantal INT NOT NULL,
Detail TEXT NULL,
Gesynchroniseerd DATETIME NOT NULL,
CONSTRAINT fk_phuidig_school FOREIGN KEY (School_ID)
REFERENCES Scholen (School_ID) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS PIVOT_instellingen (
Sleutel VARCHAR(50) NOT NULL PRIMARY KEY,
Waarde VARCHAR(255) NULL,
Bijgewerkt DATETIME NULL,
Door VARCHAR(100) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS IP_blokkades (
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Reeks VARCHAR(64) NOT NULL,
Soort VARCHAR(10) NOT NULL DEFAULT 'blokkeren',
Opmerking VARCHAR(255) NULL,
Scholen VARCHAR(1000) NULL,
Aangemaakt DATETIME NOT NULL,
Door VARCHAR(100) NULL,
Gebruiker_ID INT NULL,
Aantal_geweigerd INT NOT NULL DEFAULT 0,
Laatst_geweigerd DATETIME NULL,
UNIQUE KEY uq_ip_reeks (Reeks, Soort)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS GoPro_verzameltabel (
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
School_code VARCHAR(32) NOT NULL,
School_naam VARCHAR(255) NULL,
Person_ID VARCHAR(64) NOT NULL,
Voornaam VARCHAR(100) NULL,
Achternaam VARCHAR(100) NULL,
Email VARCHAR(255) NULL,
UPN VARCHAR(255) NULL,
Instellingsnummer VARCHAR(20) NULL,
Functie VARCHAR(100) NULL,
Rol VARCHAR(100) NULL,
Startdatum DATE NULL,
Einddatum DATE NULL,
Telefoon VARCHAR(50) NULL,
Toegevoegd DATETIME NOT NULL,
Door VARCHAR(255) NULL,
Soort VARCHAR(10) NOT NULL DEFAULT 'groen', -- groen = in de CSV, genegeerd = rode lijst, verzonden = al naar GO! Pro
Verzonden DATETIME NULL,
Verzonden_door VARCHAR(255) NULL,
UNIQUE KEY uq_gopro_verz (School_code, Person_ID),
KEY idx_gopro_verz_email (Email),
KEY idx_gopro_verz_soort (Soort, School_naam)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Koppeling_tests (
School_ID INT NOT NULL,
Onderdeel VARCHAR(50) NOT NULL,
Ok TINYINT NULL,
Detail VARCHAR(500) NULL,
Getest_op DATETIME NOT NULL,
PRIMARY KEY (School_ID, Onderdeel),
CONSTRAINT fk_ktest_school FOREIGN KEY (School_ID) REFERENCES Scholen (School_ID) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Logs (
Log_ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
Bezochte_url VARCHAR(2048) NOT NULL,
Gebruiker_ID INT NULL,
School_ID INT NULL,
Actie VARCHAR(255) NULL,
IP VARCHAR(45) NULL,
KEY idx_logs_tijd (Timestamp),
KEY idx_logs_gebruiker (Gebruiker_ID),
CONSTRAINT fk_logs_gebruiker FOREIGN KEY (Gebruiker_ID)
REFERENCES Gebruikers (Gebruiker_ID) ON DELETE SET NULL,
CONSTRAINT fk_logs_school FOREIGN KEY (School_ID)
REFERENCES Scholen (School_ID) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Status (
Bugstatus_ID TINYINT NOT NULL PRIMARY KEY,
Omschrijving VARCHAR(50) NOT NULL,
UNIQUE KEY uq_status_omschrijving (Omschrijving)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Bugs (
Bug_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Timestamp DATETIME NOT NULL,
Omschrijving TEXT NOT NULL,
Foutcode VARCHAR(100) NULL,
Bugstatus_ID TINYINT NOT NULL DEFAULT 1,
Gebruiker_ID INT NULL,
Gebruikersnaam VARCHAR(255) NULL,
School_ID INT NULL,
Gemeld_op DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY idx_bugs_status (Bugstatus_ID),
CONSTRAINT fk_bugs_status FOREIGN KEY (Bugstatus_ID) REFERENCES Status (Bugstatus_ID),
CONSTRAINT fk_bugs_gebruiker FOREIGN KEY (Gebruiker_ID)
REFERENCES Gebruikers (Gebruiker_ID) ON DELETE SET NULL,
CONSTRAINT fk_bugs_school FOREIGN KEY (School_ID)
REFERENCES Scholen (School_ID) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT IGNORE INTO Veiligheidsgroepen (Veiligheidsgroep, Naam, Omschrijving) VALUES
(1, 'Administrator', 'Alle rechten in alle scholen; beheert gebruikers, rechten en scholen'),
(2, 'Gebruiker', 'Enkel de rechten die per school zijn aangevinkt');
INSERT IGNORE INTO Onderdelen (Code, Naam, Categorie, Volgorde) VALUES
('eigendom_bekijken', 'Eigendom bekijken', 'Chromebooks', 10),
('toestellen_uitdelen', 'Toestellen uitdelen en inleveren', 'Chromebooks', 20),
('toestellen_beheren', 'Toestelleninventaris beheren', 'Chromebooks', 30),
('toestel_blokkeren', 'Chromebook blokkeren / deblokkeren', 'Chromebooks', 40),
('herstellingen', 'Herstellingen', 'Chromebooks', 50),
('signpost', 'Signpost-toestellen', 'Chromebooks', 60),
('leerlingen_bekijken', 'Leerlingen bekijken en bewerken', 'Leerlingen', 70),
('leerlingen_synchroniseren', 'Leerlingen toevoegen en synchroniseren', 'Leerlingen', 80),
('google_wachtwoord', 'Google-wachtwoord resetten', 'Google', 90),
('google_accounts', 'Google-accounts aanmaken', 'Google', 100),
('tweestaps_codes', '2FA: back-upcodes tonen / aanmaken', 'Google', 110),
('tweestaps_uitzetten', '2FA tijdelijk uitzetten (uitzondering)', 'Google', 120),
('google_licenties', 'Google-licenties', 'Google', 130),
('gmail_delegatie', 'Mailbox-delegatie', 'Google', 140),
('smartschool', 'Smartschool-wachtwoorden & info', 'Smartschool', 150),
('smartschool_activiteit', 'Activiteit co-accounts & berichten', 'Smartschool', 160),
('afwezigheden', 'Afwezigheden leerlingen (B-codes)', 'Smartschool', 170),
('skore', 'Skore-synchronisatie (starten en plannen)', 'Smartschool', 180),
('personeel_directie', 'Personeel: aanvragen goedkeuren (directie)', 'Personeel', 190),
('personeel_secretariaat', 'Personeel: dagoverzicht (secretariaat)', 'Personeel', 200),
('qr_codes', 'QR-code generator', 'Tools', 210),
('co2', 'CO2-sensoren', 'IoT', 220),
('leerlingenaantal', 'Leerlingenaantallen (alle scholen)', 'Scholengroep', 230),
('bugs_bekijken', 'Bugs bekijken', 'Beheer', 240),
('bugs_beheren', 'Status van bugs wijzigen', 'Beheer', 250),
('nieuw_schooljaar', 'Nieuw schooljaar (accounts & toestellen)', 'Beheer', 260),
('gebruikersbeheer', 'Gebruikers & rechten van deze school', 'PIVOT', 270),
('koppelingen', 'Koppelingen van deze school', 'PIVOT', 280);
INSERT IGNORE INTO Status (Bugstatus_ID, Omschrijving) VALUES
(1, 'Nieuw'),
(2, 'In behandeling'),
(3, 'Fixed');
-- ---------------------------------------------------------------------
-- 2. School: Scholengroep Antwerpen
-- Domein, Smartschool, Informat, Google, ... vul je daarna in via
-- PIVOT › 🏫 Alle scholen beheren › Bewerken.
-- ---------------------------------------------------------------------
INSERT INTO Scholen (Code, School_naam, Domein, Hostnamen, Actief, Db_naam, Instellingen, Bijgewerkt, Bijgewerkt_door)
VALUES ('sg-antwerpen', 'Scholengroep Antwerpen', '', '', 1, 'pivot_sg_antwerpen', '{}', NOW(6), 'installatie')
ON DUPLICATE KEY UPDATE School_naam = 'Scholengroep Antwerpen';
-- ---------------------------------------------------------------------
-- 3. Gebruiker Marijn – Administrator (alle rechten in alle scholen)
-- Wachtwoord 'Binnenin10' (enkel als hash bewaard; wijzigen kan in PIVOT
-- › Gebruikers & rechten).
-- ---------------------------------------------------------------------
INSERT INTO Gebruikers (Gebruikersnaam, Veiligheidsgroep, Passwoordhash, Emailadres, Actief)
VALUES ('Marijn', 1, 'scrypt:32768:8:1$FuAWb0nan2iFSInz$18994a1f3faf96e071b0cf1bded9a32daaf481c3cd92583e08d87c6e88b018be41d4aca7369108ae01ddb2f6523ab00817f60a12b41b2d255f91ad64857e4856', NULL, 1)
ON DUPLICATE KEY UPDATE Veiligheidsgroep = 1, Passwoordhash = 'scrypt:32768:8:1$FuAWb0nan2iFSInz$18994a1f3faf96e071b0cf1bded9a32daaf481c3cd92583e08d87c6e88b018be41d4aca7369108ae01ddb2f6523ab00817f60a12b41b2d255f91ad64857e4856', Actief = 1;
-- Een administrator heeft automatisch alle rechten in elke school; deze rijen
-- maken dat ook zichtbaar in het overzicht (en blijven gelden als hij ooit
-- gewone gebruiker wordt).
INSERT IGNORE INTO Gebruiker_rechten (Gebruiker_ID, School_ID, Onderdeel_ID, Toegekend_door)
SELECT g.Gebruiker_ID, s.School_ID, o.Onderdeel_ID, 'installatie'
FROM Gebruikers g CROSS JOIN Scholen s CROSS JOIN Onderdelen o
WHERE g.Gebruikersnaam = 'Marijn' AND s.Code = 'sg-antwerpen';
-- ---------------------------------------------------------------------
-- 4. Database van Scholengroep Antwerpen
-- ---------------------------------------------------------------------
CREATE DATABASE IF NOT EXISTS `pivot_sg_antwerpen` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE `pivot_sg_antwerpen`;
-- =====================================================================
-- PIVOT 1.1.0 – database van ÉÉN school (structuur schooljaar 2026-27)
--
-- Elke school in PIVOT heeft een eigen database met deze tabellen.
-- Gebruik: USE <database_van_de_school>; SOURCE school.sql;
-- of: python beheer.py nieuwe-schooldatabase <database>
--
-- Tabellen uit de PDF: Campus, Lokalen, Wifi, Toestellen, Signpost_DB,
-- Opmerkingen, Signpost_herstellingen_DB, Leerlingen, Eigendom,
-- Co_accounts, CO2_Metingen.
-- Aanvullingen die PIVOT nodig heeft staan gemarkeerd met -- [+]
-- (Scholen, Gebruikers, Logs, Bugs en Status staan in de centrale database.)
-- =====================================================================
-- ---------------------------------------------------------------------
-- Schooljaren [+] (Leerlingen.Schooljaar_ID = beginjaar, bv. 2026 → '2026-27')
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS Schooljaar (
Schooljaar_ID SMALLINT NOT NULL PRIMARY KEY,
Schooljaar VARCHAR(9) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT IGNORE INTO Schooljaar (Schooljaar_ID, Schooljaar) VALUES
(2022, '2022-23'), (2023, '2023-24'), (2024, '2024-25'), (2025, '2025-26'),
(2026, '2026-27'), (2027, '2027-28'), (2028, '2028-29'), (2029, '2029-30'),
(2030, '2030-31'), (2031, '2031-32'), (2032, '2032-33'), (2033, '2033-34'),
(2034, '2034-35'), (2035, '2035-36');
-- ---------------------------------------------------------------------
-- Campus → Lokalen
-- School_ID verwijst naar Scholen.School_ID in de CENTRALE database.
-- (Geen harde foreign key: een schooldatabase kan op een andere server staan.)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS Campus (
Campus_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
School_ID INT NOT NULL,
Campus_naam VARCHAR(255) NOT NULL,
Adres VARCHAR(255) NULL,
KEY idx_campus_school (School_ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Lokalen (
Lokaal_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Naam VARCHAR(100) NOT NULL,
Campus_ID INT NULL, -- leeg = nog niet aan een campus gekoppeld (bv. nieuw CO2-lokaal)
Verdieping VARCHAR(20) NULL,
KEY idx_lokalen_naam (Naam),
CONSTRAINT fk_lokalen_campus FOREIGN KEY (Campus_ID)
REFERENCES Campus (Campus_ID) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Wifi (
Wifi_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Campus_ID INT NULL, -- [+] op welke campus dit netwerk hoort
Naam_Netwerk VARCHAR(100) NOT NULL,
Wifi_ww VARCHAR(255) NULL,
CONSTRAINT fk_wifi_campus FOREIGN KEY (Campus_ID)
REFERENCES Campus (Campus_ID) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ---------------------------------------------------------------------
-- Toestellen
-- Schooleigen_ID = het eigen toestelnummer van de school (vroeger KAMXM_nummer).
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS Toestellen (
Toestel_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Schooleigen_ID VARCHAR(50) NULL,
Serienummer VARCHAR(100) NULL, -- [+] nodig om het toestel in Google te (de)blokkeren
Type VARCHAR(100) NULL, -- [+] model
Status VARCHAR(20) NOT NULL DEFAULT 'Beschikbaar', -- [+] Beschikbaar / Uitgeleend / Defect
Geblokkeerd TINYINT(1) NOT NULL DEFAULT 0, -- [+] 1 = geblokkeerd in Google Admin
Afschrijfdatum DATE NULL,
Lokaal_ID INT NULL,
UNIQUE KEY uq_toestellen_schooleigen (Schooleigen_ID),
KEY idx_toestellen_serienummer (Serienummer),
KEY idx_toestellen_status (Status),
CONSTRAINT fk_toestellen_lokaal FOREIGN KEY (Lokaal_ID)
REFERENCES Lokalen (Lokaal_ID) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Gegevens van Signpost (1 rij per toestel dat via Signpost aangekocht is)
CREATE TABLE IF NOT EXISTS Signpost_DB (
Toestel_ID INT NOT NULL PRIMARY KEY,
Signpostnummer VARCHAR(50) NULL,
Aankoopbedrag DECIMAL(10,2) NULL,
Aankoopdatum DATE NULL,
Garantie DATE NULL,
UNIQUE KEY uq_signpost_nummer (Signpostnummer),
CONSTRAINT fk_signpost_toestel FOREIGN KEY (Toestel_ID)
REFERENCES Toestellen (Toestel_ID) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Opmerkingen (
Opmerking_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Toestel_ID INT NOT NULL,
Opmerking TEXT NOT NULL,
Timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
Gebruiker VARCHAR(255) NULL, -- [+] wie de opmerking schreef
KEY idx_opmerkingen_toestel (Toestel_ID, Timestamp),
CONSTRAINT fk_opmerkingen_toestel FOREIGN KEY (Toestel_ID)
REFERENCES Toestellen (Toestel_ID) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ---------------------------------------------------------------------
-- Leerlingen
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS Leerlingen (
Leerling_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Internnummer VARCHAR(32) NOT NULL,
Gebruikersnaam VARCHAR(100) NULL,
Naam VARCHAR(100) NULL,
Voornaam VARCHAR(100) NULL,
SS_nummer VARCHAR(255) NULL,
Google_adres VARCHAR(255) NULL,
Schooljaar_ID SMALLINT NULL, -- [+] zie tabel Schooljaar
Vertrokken_op DATE NULL, -- niet meer actief in Informat sinds (NULL = actief)
UNIQUE KEY uq_leerlingen_internnummer (Internnummer),
KEY idx_leerlingen_gebruikersnaam (Gebruikersnaam)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Co_accounts (
Co_account_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Internnummer VARCHAR(32) NOT NULL,
Naam VARCHAR(100) NULL,
Voornaam VARCHAR(100) NULL,
Laatste_aanmelding DATETIME NULL,
Emailadres_co_accounts VARCHAR(255) NULL,
KEY idx_coaccounts_intern (Internnummer),
CONSTRAINT fk_coaccounts_leerling FOREIGN KEY (Internnummer)
REFERENCES Leerlingen (Internnummer) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ---------------------------------------------------------------------
-- Eigendom: welk toestel heeft welke leerling (ook de geschiedenis).
-- Datum_inlevering leeg = de leerling heeft het toestel nu.
-- (Vervangt de vroegere tabel Eigendom_archief.)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS Eigendom (
Eigendom_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Internnummer VARCHAR(32) NOT NULL,
Toestel_ID INT NOT NULL,
Status TINYINT NOT NULL DEFAULT 0, -- 0 = actief, 1 = geblokkeerd in Google
Datum_toekenning DATE NOT NULL,
Datum_inlevering DATE NULL,
KEY idx_eigendom_leerling (Internnummer, Datum_inlevering),
KEY idx_eigendom_toestel (Toestel_ID, Datum_inlevering),
CONSTRAINT fk_eigendom_leerling FOREIGN KEY (Internnummer)
REFERENCES Leerlingen (Internnummer) ON UPDATE CASCADE,
CONSTRAINT fk_eigendom_toestel FOREIGN KEY (Toestel_ID)
REFERENCES Toestellen (Toestel_ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ---------------------------------------------------------------------
-- Herstellingen (via Signpost of intern)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS Signpost_herstellingen_DB (
Incident_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Toestel_ID INT NOT NULL,
Omschrijving TEXT NULL,
Kostprijs DECIMAL(10,2) NULL,
Status_herstelling VARCHAR(30) NOT NULL DEFAULT 'geregistreerd',
Datum DATE NULL, -- [+] datum van de melding
Leerling_ID INT NULL, -- [+] leerling die het toestel binnenbracht
KEY idx_herstellingen_toestel (Toestel_ID),
CONSTRAINT fk_herstellingen_toestel FOREIGN KEY (Toestel_ID)
REFERENCES Toestellen (Toestel_ID) ON DELETE CASCADE,
CONSTRAINT fk_herstellingen_leerling FOREIGN KEY (Leerling_ID)
REFERENCES Leerlingen (Leerling_ID) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ---------------------------------------------------------------------
-- CO2-metingen per lokaal
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS CO2_Metingen (
Meting_ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Lokaal_ID INT NOT NULL,
ppm INT NOT NULL,
Timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY idx_co2_lokaal_tijd (Lokaal_ID, Timestamp),
KEY idx_co2_tijd (Timestamp),
CONSTRAINT fk_co2_lokaal FOREIGN KEY (Lokaal_ID)
REFERENCES Lokalen (Lokaal_ID) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- =====================================================================
-- [+] Tabellen van PIVOT-modules die niet in de PDF staan
-- (PIVOT maakt ze ook zelf aan bij het eerste gebruik)
-- =====================================================================
CREATE TABLE IF NOT EXISTS smartschool_afwezigheden (
Datum DATE NOT NULL,
Internnummer VARCHAR(32) NOT NULL,
Dagdeel CHAR(2) NOT NULL,
Code VARCHAR(8) NOT NULL,
PRIMARY KEY (Datum, Internnummer, Dagdeel),
INDEX idx_intern (Internnummer),
INDEX idx_code (Code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS smartschool_afwezigheden_sync (
Datum DATE NOT NULL PRIMARY KEY,
Opgehaald DATETIME NOT NULL,
Aantal INT NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS tweestaps_uitzonderingen (
ID INT AUTO_INCREMENT PRIMARY KEY,
Email VARCHAR(255) NOT NULL,
Naam VARCHAR(255) NULL,
Reden VARCHAR(255) NULL,
Van DATETIME NOT NULL,
Tot DATETIME NOT NULL,
Door VARCHAR(100) NULL,
Actief TINYINT NOT NULL DEFAULT 1,
Beeindigd_op DATETIME NULL,
Beeindigd_door VARCHAR(100) NULL,
INDEX idx_actief (Actief, Tot),
INDEX idx_email (Email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS tweestaps_log (
ID INT AUTO_INCREMENT PRIMARY KEY,
Tijdstip DATETIME NOT NULL,
Door VARCHAR(100) NULL,
Actie VARCHAR(40) NOT NULL,
Email VARCHAR(255) NOT NULL,
Details VARCHAR(255) NULL,
INDEX idx_tijdstip (Tijdstip)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS gmail_delegatie_log (
ID INT AUTO_INCREMENT PRIMARY KEY,
Tijdstip DATETIME NOT NULL,
Gebruiker VARCHAR(100) NULL,
Actie VARCHAR(20) NOT NULL,
Mailbox VARCHAR(255) NOT NULL,
Gedelegeerde VARCHAR(255) NOT NULL,
INDEX idx_mailbox (Mailbox),
INDEX idx_tijdstip (Tijdstip)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS gmail_delegaties (
Mailbox VARCHAR(255) NOT NULL,
Mailbox_naam VARCHAR(255) NULL,
Gedelegeerde VARCHAR(255) NOT NULL,
Gedelegeerde_naam VARCHAR(255) NULL,
Status VARCHAR(20) NULL,
Opgehaald DATETIME NOT NULL,
PRIMARY KEY (Mailbox, Gedelegeerde),
KEY idx_gmail_deleg_gedelegeerde (Gedelegeerde)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS gmail_delegaties_scan (
ID TINYINT NOT NULL PRIMARY KEY,
Opgehaald DATETIME NULL,
Mailboxen INT NULL,
Fouten INT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS internaat_aanwezigheid (
Datum DATE NOT NULL,
Persoon_ID VARCHAR(64) NOT NULL, -- pPersoon/persoonId uit de Internaat-API van Informat
Moment VARCHAR(10) NOT NULL, -- ochtend | avond
Status VARCHAR(10) NOT NULL, -- aanwezig | afwezig (geen rij = nog niet gecontroleerd)
Naam VARCHAR(200) NULL,
Bijgewerkt DATETIME NOT NULL,
Door VARCHAR(255) NULL,
PRIMARY KEY (Datum, Persoon_ID, Moment),
KEY idx_aanw_persoon (Persoon_ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS gmail_label_log (
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Gestart DATETIME NOT NULL,
Klaar DATETIME NULL,
Door VARCHAR(255) NULL,
Bron VARCHAR(255) NOT NULL,
Label VARCHAR(255) NOT NULL,
Doel VARCHAR(255) NOT NULL,
Modus VARCHAR(12) NOT NULL, -- kopieren | verplaatsen
Totaal INT NULL,
Gelukt INT NULL,
Overgeslagen INT NULL,
Fouten INT NULL,
Melding VARCHAR(500) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS gmail_label_items (
Bron VARCHAR(255) NOT NULL,
Bron_ID VARCHAR(64) NOT NULL, -- Gmail-id in de bronmailbox
Doel VARCHAR(255) NOT NULL,
Doel_ID VARCHAR(64) NULL, -- Gmail-id van de kopie in de doelmailbox
Gekopieerd DATETIME NOT NULL,
PRIMARY KEY (Bron, Bron_ID, Doel)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Gmail-handtekeningen: sjabloon, logo en gekozen OU's (één rij) en wanneer de handtekening per gebruiker gezet werd
CREATE TABLE IF NOT EXISTS gmail_handtekening (
ID TINYINT NOT NULL PRIMARY KEY,
Sjabloon MEDIUMTEXT NULL,
OUs TEXT NULL,
Met_sub_ous TINYINT NOT NULL DEFAULT 1,
Logo MEDIUMBLOB NULL,
Logo_type VARCHAR(40) NULL,
Logo_sleutel VARCHAR(40) NULL,
Logo_url VARCHAR(500) NULL,
Logo_breedte INT NOT NULL DEFAULT 120,
Publiek_adres VARCHAR(255) NULL,
Nachtelijk TINYINT NOT NULL DEFAULT 0,
Laatste_nacht DATE NULL,
Nacht_resultaat VARCHAR(500) NULL,
Bijgewerkt DATETIME NULL,
Door VARCHAR(255) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS gmail_handtekening_log (
Email VARCHAR(255) NOT NULL PRIMARY KEY,
Toegepast DATETIME NOT NULL,
Ok TINYINT NOT NULL,
Melding VARCHAR(500) NULL,
Hash CHAR(40) NULL,
Door VARCHAR(255) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Gmail › Contacten: contactlijsten die PIVOT in de mailboxen van de gekozen OU's zet
CREATE TABLE IF NOT EXISTS contact_lijsten (
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Naam VARCHAR(100) NOT NULL, -- label in Google Contacten
OUs TEXT NULL, -- JSON-lijst van OU-paden
Met_sub_ous TINYINT NOT NULL DEFAULT 1,
Bijgewerkt DATETIME NULL,
Door VARCHAR(255) NULL,
Laatste_sync DATETIME NULL,
Resultaat VARCHAR(500) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS contact_lijst_items (
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Lijst_ID INT NOT NULL,
Voornaam VARCHAR(100) NULL,
Achternaam VARCHAR(100) NULL,
Organisatie VARCHAR(150) NULL,
Functie VARCHAR(150) NULL,
Email VARCHAR(255) NULL,
Telefoon VARCHAR(60) NULL,
Notitie VARCHAR(500) NULL,
KEY idx_cli_lijst (Lijst_ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS google_licenties (
SKU_ID VARCHAR(32) NOT NULL PRIMARY KEY,
Naam VARCHAR(128) NOT NULL,
Aangekocht INT NOT NULL DEFAULT 0,
Bijgewerkt DATETIME NULL,
Bijgewerkt_door VARCHAR(100) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS personeel_aanvragen (
ID INT AUTO_INCREMENT PRIMARY KEY,
Soort VARCHAR(20) NOT NULL,
Status VARCHAR(20) NOT NULL,
Email VARCHAR(255) NOT NULL,
Naam VARCHAR(255) NULL,
Ingediend_door VARCHAR(255) NULL,
Titel VARCHAR(255) NOT NULL,
Omschrijving TEXT NULL,
Locatie VARCHAR(255) NULL,
Van_datum DATE NOT NULL,
Tot_datum DATE NOT NULL,
Dagdeel VARCHAR(10) NOT NULL DEFAULT 'dag',
Lesuren VARCHAR(50) NULL,
Klassen TEXT NULL,
Begeleiders TEXT NULL,
Kost DECIMAL(10,2) NULL,
Vervanging_ok TINYINT NOT NULL DEFAULT 0,
Vervanging_info VARCHAR(255) NULL,
Aangemaakt DATETIME NOT NULL,
Bijgewerkt DATETIME NOT NULL,
INDEX idx_status (Status),
INDEX idx_datum (Van_datum, Tot_datum),
INDEX idx_email (Email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS personeel_reacties (
ID INT AUTO_INCREMENT PRIMARY KEY,
Aanvraag_ID INT NOT NULL,
Tijdstip DATETIME NOT NULL,
Email VARCHAR(255) NULL,
Naam VARCHAR(255) NULL,
Actie VARCHAR(30) NOT NULL,
Tekst TEXT NULL,
INDEX idx_aanvraag (Aanvraag_ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Skore-synchronisatie (planning + logboek)
CREATE TABLE IF NOT EXISTS skore_planning (
ID TINYINT NOT NULL PRIMARY KEY,
Frequentie VARCHAR(20) NOT NULL DEFAULT 'uit',
Uur TINYINT NOT NULL DEFAULT 6,
Minuut TINYINT NOT NULL DEFAULT 0,
Weekdag TINYINT NOT NULL DEFAULT 0,
Dag_van_maand TINYINT NOT NULL DEFAULT 1,
Laatst_gepland DATETIME NULL,
Bijgewerkt DATETIME NULL,
Bijgewerkt_door VARCHAR(255) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS skore_log (
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Gestart DATETIME NOT NULL,
Door VARCHAR(255) NULL,
Manier VARCHAR(20) NOT NULL,
Service_ID VARCHAR(100) NULL,
Status VARCHAR(30) NOT NULL,
Melding TEXT NULL,
Bijgewerkt DATETIME NULL,
INDEX idx_skore_gestart (Gestart)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT IGNORE INTO skore_planning (ID) VALUES (1);
CREATE TABLE IF NOT EXISTS smartschool_coaccounts (
Internnummer VARCHAR(32) NOT NULL,
Nr TINYINT NOT NULL,
Gebruikersnaam VARCHAR(100) NULL,
Leerling_naam VARCHAR(100) NULL,
Leerling_voornaam VARCHAR(100) NULL,
Klas VARCHAR(50) NULL,
Voornaam VARCHAR(100) NULL,
Naam VARCHAR(100) NULL,
Type VARCHAR(50) NULL,
Email VARCHAR(255) NULL,
Laatste_login DATETIME NULL,
Opgehaald DATETIME NOT NULL,
PRIMARY KEY (Internnummer, Nr),
KEY idx_coacc_klas (Klas)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS gopro_keuzes (
Person_ID VARCHAR(64) NOT NULL PRIMARY KEY,
Functie VARCHAR(100) NULL,
Rol VARCHAR(100) NULL,
Bijgewerkt DATETIME NOT NULL,
Door VARCHAR(255) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;