To properly link recordings to concerts, and thus tie each recording to the actual concert performance where it occurred, you'll want to:
- Replace the ambiguous
concertandvenuefields (currently just strings) with a foreign key reference to theconcertstable. - Optionally retain or rename other fields (like
venue) only if they are recording-specific and not redundant with what's inconcerts.
β
Updated recordings Table Definition
Here is the improved version of the recordings table:
DROP TABLE IF EXISTS `recordings`;/*!40101 SET @saved_cs_client = @@character_set_client */;/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `recordings` ( `id_recording` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Unique ID for this recording', `catalog_number` varchar(5) NOT NULL COMMENT 'Catalog number of the composition', `id_concert` int(11) NOT NULL COMMENT 'Which concert this recording is from', `name` varchar(255) DEFAULT NULL COMMENT 'Name of the piece or excerpt on the recording', `ensemble` varchar(2048) DEFAULT NULL COMMENT 'Ensemble or performer name', `link` varchar(512) DEFAULT NULL COMMENT 'URL or path to the audio or video recording', `composer` varchar(255) DEFAULT NULL COMMENT 'Composer for labeling purposes', `arranger` varchar(255) DEFAULT NULL COMMENT 'Arranger for labeling purposes', `enabled` int(11) NOT NULL DEFAULT 0 COMMENT 'Enable flag for display or availability',
PRIMARY KEY (`id_recording`), KEY `catalog_number` (`catalog_number`), KEY `id_concert` (`id_concert`),
CONSTRAINT `recordings_ibfk_1` FOREIGN KEY (`catalog_number`) REFERENCES `compositions` (`catalog_number`) ON DELETE CASCADE, CONSTRAINT `recordings_ibfk_2` FOREIGN KEY (`id_concert`) REFERENCES `concerts` (`id_concert`) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='This table keeps recordings.';/*!40101 SET character_set_client = @saved_cs_client */;
π Changes Made:
- β
Added
id_concert: This links the recording directly to a concert. - π Removed
concertandvenueas free text: This avoids duplication since those values are in theconcertstable. - π Kept fields like
composer,arranger, andensemble: Useful for labeling and searchability, even if technically redundant.
π‘ Bonus Query Idea:
Get all recordings from a concert:
SELECT r.name AS recording_name, r.link, c.performance_date, c.venue, p.title AS program_title FROM recordings r JOIN concerts c ON r.id_concert = c.id_concert JOIN playgrams p ON c.id_playgram = p.id_playgram WHERE c.performance_date = '2025-06-09';
Let me know if youβd like to normalize composer/arranger into their own tables or include indexing suggestions!
Great β since you're transitioning from a flat recordings table to a normalized schema using concerts, weβll write a migration query in two parts:
β
1. Insert into concerts from old recordings table
We'll generate unique concerts based on combinations of date, venue, and a placeholder or derived playgram.
If you're not yet assigning a real playgram, you can insert a dummy one and update later.
-- 1a. Create a dummy playgram (if none exist)INSERT IGNORE INTO playgrams (title, description)VALUES ('Imported Legacy', 'Auto-generated for imported recordings');
-- 1b. Get its IDSET @default_playgram_id = ( SELECT id_playgram FROM playgrams WHERE title = 'Imported Legacy');
-- 1c. Insert unique concert entries from old recordingsINSERT INTO concerts (id_playgram, performance_date, venue, conductor, notes)SELECT DISTINCT @default_playgram_id AS id_playgram, `date` AS performance_date, `venue`, 'Unknown' AS conductor, CONCAT('Imported from recording entry: ', `name`) AS notesFROM recordingsWHERE `date` IS NOT NULL AND `venue` IS NOT NULL;
β
2. Insert into the new recordings table using concerts.id_concert
Youβll now map each legacy recording row to its matching concert.
INSERT INTO recordings (
catalog_number,
id_concert,
name,
ensemble,
link,
composer,
arranger,
enabled
)
SELECT
r.catalog_number,
c.id_concert,
r.name,
r.ensemble,
r.link,
r.composer,
r.arranger,
r.enabled
FROM recordings r
JOIN concerts c
ON r.date = c.performance_date
AND r.venue = c.venue;
π Notes:- This assumes every
(date, venue)combo is unique per concert. - The dummy playgram can be updated later with real content and linked appropriately.
- You can verify how many concerts were created:
SELECT COUNT(*) FROM concerts WHERE id_playgram = @default_playgram_id;
Hereβs a safe rollback script that undoes the migration from the old recordings table to the new concerts and normalized recordings structure β specifically the data we just inserted based on the "Imported Legacy" placeholder.
β What This Does
-
Step 1 retrieves the ID of the dummy playgram ("Imported Legacy").
-
Step 2 deletes all recordings that were linked to concerts using that playgram.
-
Step 3 deletes the concerts themselves.
-
Step 4 removes the dummy playgram.
This approach only removes what was inserted by the migration process, keeping your original recordings table untouched.
π Rollback Script
-- Step 1: Get the playgram ID used for imported legacy data
SELECT @imported_playgram_id := id_playgram
FROM playgrams
WHERE title = 'Imported Legacy';
-- Step 2: Delete recordings that reference concerts from that playgram
DELETE FROM recordings
WHERE id_concert IN (
SELECT id_concert
FROM concerts
WHERE id_playgram = @imported_playgram_id
);
-- Step 3: Delete the concerts tied to that playgram
DELETE FROM concerts
WHERE id_playgram = @imported_playgram_id;
-- Step 4: Finally, delete the placeholder playgram itself
DELETE FROM playgrams
WHERE id_playgram = @imported_playgram_id;