# 메뉴 삭제 검증 쿼리 메뉴 영구 삭제 전/후 연관 데이터 확인용 SQL 쿼리 ## 삭제 전 확인 쿼리 ### 1. 특정 메뉴의 연관 권한 조회 ```sql -- 메뉴 ID를 기준으로 연관 권한 조회 -- {MENU_ID}를 실제 메뉴 ID로 변경 SELECT p.id, p.name, p.guard_name, p.tenant_id FROM permissions p WHERE p.name LIKE 'menu:{MENU_ID}.%' ORDER BY p.name; ``` ### 2. 역할-권한 연결 조회 ```sql -- 해당 메뉴 권한이 어떤 역할에 할당되어 있는지 확인 SELECT r.id AS role_id, r.name AS role_name, r.tenant_id, p.name AS permission_name FROM role_has_permissions rhp JOIN roles r ON rhp.role_id = r.id JOIN permissions p ON rhp.permission_id = p.id WHERE p.name LIKE 'menu:{MENU_ID}.%' ORDER BY r.name, p.name; ``` ### 3. 사용자 직접 권한 조회 ```sql -- 해당 메뉴 권한이 어떤 사용자에게 직접 할당되어 있는지 확인 SELECT u.id AS user_id, u.name AS user_name, u.email, p.name AS permission_name FROM model_has_permissions mhp JOIN users u ON mhp.model_id = u.id AND mhp.model_type = 'App\\Models\\User' JOIN permissions p ON mhp.permission_id = p.id WHERE p.name LIKE 'menu:{MENU_ID}.%' ORDER BY u.name, p.name; ``` ### 4. 부서 권한 조회 ```sql -- 해당 메뉴 권한이 어떤 부서에 할당되어 있는지 확인 SELECT d.id AS dept_id, d.name AS dept_name, d.tenant_id, p.name AS permission_name FROM model_has_permissions mhp JOIN departments d ON mhp.model_id = d.id AND mhp.model_type = 'App\\Models\\Tenants\\Department' JOIN permissions p ON mhp.permission_id = p.id WHERE p.name LIKE 'menu:{MENU_ID}.%' ORDER BY d.name, p.name; ``` ### 5. 종합 영향도 조회 (삭제 전 확인용) ```sql -- 삭제 시 영향받는 모든 데이터 요약 SELECT 'permissions' AS table_name, COUNT(*) AS record_count FROM permissions WHERE name LIKE 'menu:{MENU_ID}.%' UNION ALL SELECT 'role_has_permissions' AS table_name, COUNT(*) AS record_count FROM role_has_permissions rhp JOIN permissions p ON rhp.permission_id = p.id WHERE p.name LIKE 'menu:{MENU_ID}.%' UNION ALL SELECT 'model_has_permissions (users)' AS table_name, COUNT(*) AS record_count FROM model_has_permissions mhp JOIN permissions p ON mhp.permission_id = p.id WHERE p.name LIKE 'menu:{MENU_ID}.%' AND mhp.model_type = 'App\\Models\\User' UNION ALL SELECT 'model_has_permissions (departments)' AS table_name, COUNT(*) AS record_count FROM model_has_permissions mhp JOIN permissions p ON mhp.permission_id = p.id WHERE p.name LIKE 'menu:{MENU_ID}.%' AND mhp.model_type = 'App\\Models\\Tenants\\Department'; ``` ## 삭제 후 확인 쿼리 ### 1. 메뉴가 삭제되었는지 확인 ```sql -- 메뉴 테이블에서 해당 ID 확인 (soft delete 포함) SELECT id, name, deleted_at FROM menus WHERE id = {MENU_ID}; -- 완전히 삭제된 경우 결과 없음 ``` ### 2. 연관 권한이 삭제되었는지 확인 ```sql -- 연관 권한이 모두 삭제되었는지 확인 (결과가 0이어야 함) SELECT COUNT(*) AS remaining_permissions FROM permissions WHERE name LIKE 'menu:{MENU_ID}.%'; ``` ### 3. 역할-권한 연결이 삭제되었는지 확인 ```sql -- FK CASCADE로 자동 삭제되었는지 확인 SELECT COUNT(*) AS remaining_role_permissions FROM role_has_permissions rhp WHERE NOT EXISTS ( SELECT 1 FROM permissions p WHERE p.id = rhp.permission_id ); ``` ### 4. 아카이브에 저장되었는지 확인 ```sql -- archived_records에서 삭제 기록 조회 SELECT ar.id, ar.batch_id, ar.batch_description, ar.record_type, ar.original_id, ar.deleted_at, ar.notes, JSON_EXTRACT(ar.main_data, '$.name') AS menu_name FROM archived_records ar WHERE ar.record_type = 'menu' AND ar.original_id = {MENU_ID} ORDER BY ar.deleted_at DESC; -- 연관 테이블 데이터도 확인 SELECT arr.table_name, arr.record_count, arr.data FROM archived_record_relations arr JOIN archived_records ar ON arr.archived_record_id = ar.id WHERE ar.record_type = 'menu' AND ar.original_id = {MENU_ID}; ``` ## 글로벌 메뉴용 쿼리 글로벌 메뉴의 경우 `menu:{ID}` 대신 `global_menu:{ID}` 패턴 사용: ```sql -- 글로벌 메뉴 권한 조회 SELECT * FROM permissions WHERE name LIKE 'global_menu:{MENU_ID}.%'; -- 글로벌 메뉴 참조하는 테넌트 메뉴 확인 SELECT id, tenant_id, name, global_menu_id FROM menus WHERE global_menu_id = {MENU_ID}; -- 삭제 후 참조 해제 확인 (global_menu_id가 NULL이고 is_customized가 true) SELECT id, tenant_id, name, global_menu_id, is_customized FROM menus WHERE is_customized = 1; ``` ## 실행 예시 ```bash # MySQL 콘솔에서 실행 mysql -u root -p samdb # 또는 Laravel Tinker에서 실행 php artisan tinker >>> DB::select("SELECT * FROM permissions WHERE name LIKE 'menu:123.%'"); ``` --- **최종 업데이트**: 2025-12-09