This repository was archived by the owner on Jul 10, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvacunas-init.sql
More file actions
4520 lines (4223 loc) · 203 KB
/
vacunas-init.sql
File metadata and controls
4520 lines (4223 loc) · 203 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
USE master;
GO
-- Verifica si la base de datos ya existe
IF DB_ID('vacunas') IS NULL
BEGIN
CREATE DATABASE vacunas;
END
ELSE
BEGIN
DROP DATABASE vacunas;
CREATE DATABASE vacunas;
END
GO
USE vacunas;
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
PRINT ('Intentando crear el login si no existe');
GO
-- Únicamente las aplicaciones deben tener un login y su user con permisos
-- PUEDE CAMBIAR EL NOMBRE LOGIN_NAME Y COLOCARLO COMO DB_USER para spring
IF NOT EXISTS (SELECT *
FROM sys.server_principals
WHERE name = 'LOGIN_NAME')
BEGIN
PRINT (N'Creando el login');
CREATE LOGIN LOGIN_NAME
-- COLOCAR AQUÍ CONTRASEÑA EN TEXTO PLANO. CUIDADO AL SUBIR ESTE ARCHIVO
-- COLOCAR LUEGO COMO DB_PASSWORD para spring
WITH PASSWORD = '',
DEFAULT_DATABASE = vacunas
END
ELSE
BEGIN
PRINT ('El usuario ya existe');
END
-- crear usuario de la base de datos
-- COLOCAR EL MISMO LOGIN_NAME DE ARRIBA
PRINT (N'Creando el usuario');
BEGIN TRY
CREATE USER SpringAPI FOR LOGIN LOGIN_NAME;
END TRY
BEGIN CATCH
PRINT ('Error al crear el usuario. Detalles del error: ' + ERROR_MESSAGE());
END CATCH;
-- Verificar si el usuario existe antes de asignar permisos
IF EXISTS (SELECT *
FROM sys.database_principals
WHERE name = 'SpringAPI')
BEGIN
BEGIN TRY
PRINT (N'Otorgando permisos al user');
EXEC sp_addrolemember 'db_datareader', 'SpringApi';
EXEC sp_addrolemember 'db_datawriter', 'SpringApi';
GRANT EXECUTE ON SCHEMA::dbo TO SpringAPI;
-- dependiendo la aplicación se le puede asignar más o menos permisos**
END TRY
BEGIN CATCH
PRINT ('Error al otorgar permisos. Detalles del error: ' + ERROR_MESSAGE());
END CATCH;
END
ELSE
BEGIN
PRINT ('El usuario SpringAPI no existe, no se pueden otorgar permisos.');
END
GO
PRINT (N'Creando tablas');
GO
CREATE TABLE permisos
(
id SMALLINT PRIMARY KEY IDENTITY (1,1),
nombre NVARCHAR(100) NOT NULL,
descripcion NVARCHAR(100),
created_at DATETIME NOT NULL
CONSTRAINT df_permisos_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
CONSTRAINT uq_permisos_nombre UNIQUE (nombre),
INDEX ix_permisos_nombre (nombre)
);
GO
CREATE TABLE roles
(
id SMALLINT PRIMARY KEY IDENTITY (1,1),
nombre NVARCHAR(100) NOT NULL,
descripcion NVARCHAR(100),
created_at DATETIME NOT NULL
CONSTRAINT df_roles_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
CONSTRAINT uq_roles_nombre UNIQUE (nombre),
INDEX ix_roles_nombre (nombre)
);
GO
CREATE TABLE roles_permisos
(
rol SMALLINT,
permiso SMALLINT,
created_at DATETIME NOT NULL
CONSTRAINT df_roles_permisos_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
PRIMARY KEY (rol, permiso),
CONSTRAINT fk_roles_permisos_roles FOREIGN KEY (rol) REFERENCES roles (id) ON DELETE CASCADE,
CONSTRAINT fk_roles_permisos_permisos FOREIGN KEY (permiso) REFERENCES permisos (id) ON DELETE CASCADE
);
GO
CREATE TABLE usuarios
(
id UNIQUEIDENTIFIER PRIMARY KEY
CONSTRAINT df_usuarios_id DEFAULT NEWID(),
usuario NVARCHAR(50),
clave NVARCHAR(100) NOT NULL,
created_at DATETIME NOT NULL
CONSTRAINT df_usuarios_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
last_used DATETIME,
CONSTRAINT ck_usuarios_clave CHECK (clave LIKE '$2_$_%' AND LEN(clave) >= 60)
);
GO
CREATE UNIQUE NONCLUSTERED INDEX ix_usuarios_usuario
ON usuarios (usuario)
WHERE usuario IS NOT NULL;
GO
CREATE TABLE usuarios_roles
(
usuario UNIQUEIDENTIFIER,
rol SMALLINT,
created_at DATETIME NOT NULL
CONSTRAINT df_usuarios_roles_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
PRIMARY KEY (usuario, rol),
CONSTRAINT fk_usuarios_roles_usuarios FOREIGN KEY (usuario) REFERENCES usuarios (id) ON DELETE CASCADE,
CONSTRAINT fk_usuarios_roles_roles FOREIGN KEY (rol) REFERENCES roles (id) ON DELETE CASCADE
);
GO
CREATE TABLE provincias
(
id TINYINT PRIMARY KEY IDENTITY (0,1),
nombre NVARCHAR(30) NOT NULL,
CONSTRAINT ck_provincia_existe CHECK (nombre IN
('Por registrar', /* Problemas o nueva provincia sin registrar aún */
'Bocas del Toro', /* 1 */
N'Coclé', /* 2 */
N'Colón', /* 3 */
N'Chiriquí', /* 4 */
N'Darién', /* 5 */
'Herrera', /* 6 */
'Los Santos', /* 7 */
N'Panamá', /* 8 */
'Veraguas', /* 9 */
'Guna Yala', /* 10 */
N'Emberá-Wounaan', /* 11*/
N'Ngäbe-Buglé',/* 12 */
N'Panamá Oeste', /* 13 */
N'Naso Tjër Di', /* 14 */
/* No Fijas, pueden moverse por nuevas provincias o comarcas nivel provincia oficiales. Orden dado por número de cédula panameña */
N'Guna de Madugandí', /*15 comarca nivel corregimiento */
N'Guna de Wargandí', /*16 comarca nivel corregimiento */
'Extranjero' /* 17 */
)),
INDEX ix_provincias_nombre (nombre)
);
GO
CREATE TABLE distritos
(
id TINYINT PRIMARY KEY IDENTITY (0,1),
nombre NVARCHAR(100) NOT NULL,
provincia TINYINT NOT NULL,
CONSTRAINT ck_distritos_provincias CHECK (
(provincia = 0 AND nombre LIKE 'Por registrar') OR
(provincia = 1 AND nombre IN ('Almirante',
'Bocas del Toro',
'Changuinola',
N'Chiriquí Grande')) OR
(provincia = 2 AND nombre IN ('Aguadulce',
N'Antón',
'La Pintada',
N'Natá',
N'Olá',
N'Penonomé')) OR
(provincia = 3 AND nombre IN ('Chagres',
N'Colón',
'Donoso',
'Portobelo',
'Santa Isabel',
'Omar Torrijos Herrera')) OR
(provincia = 4 AND nombre IN ('Alanje',
N'Barú',
N'Boquerón',
'Boquete',
'Bugaba',
'David',
'Dolega',
'Gualaca',
'Remedios',
'Renacimiento',
N'San Félix',
'San Lorenzo',
'Tierras Altas',
N'Tolé')) OR
(provincia = 5 AND nombre IN ('Chepigana',
'Pinogana',
'Santa Fe',
N'Guna de Wargandí')) OR
(provincia = 6 AND nombre IN (N'Chitré',
'Las Minas',
'Los Pozos',
N'Ocú',
'Parita',
N'Pesé',
N'Santa María')) OR
(provincia = 7 AND nombre IN (N'Guararé',
'Las Tablas',
'Los Santos',
'Macaracas',
N'Pedasí',
N'Pocrí',
N'Tonosí')) OR
(provincia = 8 AND nombre IN ('Balboa',
'Chepo',
N'Chimán',
N'Panamá',
'San Miguelito',
'Taboga')) OR
(provincia = 9 AND nombre IN ('Atalaya',
'Calobre',
N'Cañazas',
'La Mesa',
'Las Palmas',
'Mariato',
'Montijo',
N'Río de Jesús',
'San Francisco',
'Santa Fe',
'Santiago',
N'Soná')) OR
/* comarca Guna Yala, Madugandí, Wargandí no tiene distrito, provincia 10 */
(provincia = 11 AND nombre IN (N'Cémaco', N'Sambú')) OR
(provincia = 12 AND nombre IN (N'Besikó',
'Jirondai',
N'Kankintú',
N'Kusapín',
N'Mironó',
N'Müna',
'Nole Duima',
N'Ñürüm',
'Santa Catalina',
N'Calovébora')) OR
(provincia = 13 AND nombre IN (N'Arraiján',
'Capira',
'Chame',
'La Chorrera',
'San Carlos')) OR
(provincia = 14 AND nombre IN (N'Naso Tjër Di')) OR
(provincia = 17 AND nombre IN ('Extranjero')) OR
(provincia IS NULL AND nombre IS NULL) -- Permitir NULL si es necesario
),
CONSTRAINT fk_distritos_provincias FOREIGN KEY (provincia) REFERENCES provincias (id),
INDEX ix_distritos_nombre (nombre)
);
GO
CREATE TABLE direcciones
(
id UNIQUEIDENTIFIER PRIMARY KEY
CONSTRAINT df_direcciones_id DEFAULT NEWID(),
direccion VARCHAR(150) NOT NULL,
distrito TINYINT NOT NULL
CONSTRAINT df_direcciones_distrito DEFAULT 0,
created_at DATETIME NOT NULL
CONSTRAINT df_direcciones_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
CONSTRAINT fk_direcciones_distritos FOREIGN KEY (distrito) REFERENCES distritos (id),
INDEX ix_direcciones_direccion (direccion)
);
GO
CREATE TABLE personas
(
id UNIQUEIDENTIFIER PRIMARY KEY
CONSTRAINT df_personas_id DEFAULT NEWID(),
cedula VARCHAR(15),
pasaporte VARCHAR(20),
nombre NVARCHAR(100),
nombre2 NVARCHAR(100),
apellido1 NVARCHAR(100),
apellido2 NVARCHAR(100),
correo VARCHAR(254),
telefono VARCHAR(15),
fecha_nacimiento SMALLDATETIME,
edad TINYINT,
sexo CHAR(1)
CONSTRAINT df_personas_sexo DEFAULT ('X'),
estado NVARCHAR(50) NOT NULL
CONSTRAINT df_personas_estado DEFAULT ('NO_VALIDADO'),
disabled BIT
CONSTRAINT df_personas_disabled DEFAULT (0),
direccion UNIQUEIDENTIFIER NOT NULL,
usuario UNIQUEIDENTIFIER,
CONSTRAINT ck_personas_sexo CHECK (sexo LIKE 'M' OR sexo LIKE 'F' OR sexo LIKE 'X'),
CONSTRAINT ck_personas_telefono CHECK (telefono IS NULL OR (telefono LIKE '+[0-9]%' AND LEN(telefono) >= 5 AND
TRY_CAST(SUBSTRING(telefono, 2, LEN(telefono)) AS BIGINT) IS NOT NULL)),
CONSTRAINT ck_personas_cedula CHECK (cedula IS NULL OR (
(cedula LIKE 'PE-%' OR cedula LIKE 'E-%' OR cedula LIKE 'N-%' OR cedula LIKE '[1-9]-%' OR
cedula LIKE '[10-13]-%'
OR cedula LIKE '[1-9]AV-%' OR cedula LIKE '[10-13]AV-%' OR cedula LIKE '[1-9]PI-%' OR
cedula LIKE '[10-13]PI-%')
AND cedula LIKE '%-[0-9][0-9][0-9][0-9]-%'
AND cedula LIKE '%-[0-9][0-9][0-9][0-9][0-9][0-9]')),
CONSTRAINT ck_personas_pasaporte CHECK (pasaporte LIKE '[A-Z0-9]%' AND LEN(pasaporte) >= 5),
CONSTRAINT ck_personas_fecha_nacimiento CHECK (fecha_nacimiento IS NULL OR fecha_nacimiento <= GETDATE()),
CONSTRAINT ck_personas_estado CHECK (estado IN ('ACTIVO', 'NO_VALIDADO', 'FALLECIDO', 'INACTIVO', 'DESACTIVADO')),
CONSTRAINT ck_personas_identificacion CHECK ((cedula IS NOT NULL) OR (pasaporte IS NOT NULL)),
CONSTRAINT fk_personas_direcciones FOREIGN KEY (direccion) REFERENCES direcciones (id) ON UPDATE CASCADE,
CONSTRAINT fk_personas_usuarios FOREIGN KEY (usuario) REFERENCES usuarios (id) ON UPDATE CASCADE,
INDEX ix_personas_nombres_apellidos (nombre, nombre2, apellido1, apellido2)
)
GO
CREATE UNIQUE NONCLUSTERED INDEX ix_personas_cedula
ON personas (cedula)
WHERE cedula IS NOT NULL;
GO
CREATE UNIQUE NONCLUSTERED INDEX ix_personas_pasaporte
ON personas (pasaporte)
WHERE pasaporte IS NOT NULL;
GO
CREATE UNIQUE NONCLUSTERED INDEX ix_personas_correo
ON personas (correo)
WHERE correo IS NOT NULL;
GO
CREATE UNIQUE NONCLUSTERED INDEX ix_personas_telefono
ON personas (telefono)
WHERE telefono IS NOT NULL;
GO
CREATE UNIQUE NONCLUSTERED INDEX ix_personas_usuario
ON personas (usuario)
WHERE usuario IS NOT NULL;
GO
CREATE TABLE entidades
(
id UNIQUEIDENTIFIER PRIMARY KEY
CONSTRAINT df_entidades_id DEFAULT NEWID(),
nombre NVARCHAR(100) NOT NULL,
correo VARCHAR(254),
telefono VARCHAR(15),
dependencia NVARCHAR(13),
estado NVARCHAR(50) NOT NULL
CONSTRAINT df_entidades_estado DEFAULT ('ACTIVO'),
disabled BIT
CONSTRAINT df_entidades_disabled DEFAULT (0),
direccion UNIQUEIDENTIFIER NOT NULL,
CONSTRAINT ck_entidades_correo CHECK (correo IS NULL OR (correo LIKE '%_@_%.__%' AND LEN(correo) >= 5)),
CONSTRAINT ck_entidades_telefono CHECK (telefono IS NULL OR (telefono LIKE '+[0-9]%' AND LEN(telefono) >= 5 AND
TRY_CAST(SUBSTRING(telefono, 2, LEN(telefono)) AS BIGINT) IS NOT NULL)),
CONSTRAINT ck_entidades_dependencia CHECK (dependencia IS NULL OR
dependencia IN ('CSS', 'MINSA', 'PRIVADA', 'POR_REGISTRAR')),
CONSTRAINT ck_entidades_estado CHECK (estado IN ('ACTIVO', 'NO_VALIDADO', 'INACTIVO', 'DESACTIVADO')),
CONSTRAINT fk_entidades_direcciones FOREIGN KEY (direccion) REFERENCES direcciones (id) ON UPDATE CASCADE,
);
GO
CREATE UNIQUE NONCLUSTERED INDEX ix_entidades_correo
ON entidades (correo)
WHERE correo IS NOT NULL;
GO
CREATE UNIQUE NONCLUSTERED INDEX ix_entidades_telefono
ON entidades (telefono)
WHERE telefono IS NOT NULL;
GO
CREATE TABLE pacientes
(
id UNIQUEIDENTIFIER PRIMARY KEY,
identificacion_temporal VARCHAR(255),
created_at DATETIME NOT NULL
CONSTRAINT df_pacientes_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
CONSTRAINT ck_pacientes_id_temporal CHECK (
-- opción 1 no identificado
(identificacion_temporal LIKE 'NI-%') OR
-- opción 2 recién nacidos
((identificacion_temporal LIKE 'RN-%' OR
(identificacion_temporal LIKE ('RN[1-9]-%') OR identificacion_temporal LIKE ('RN[1-9][1-9]-%')) AND
(identificacion_temporal LIKE '%-PE-%' OR identificacion_temporal LIKE '%-E-%' OR
identificacion_temporal LIKE '%-N-%' OR identificacion_temporal LIKE '%-[1-13]%')
AND identificacion_temporal LIKE '%-[0-9][0-9][0-9][0-9]-%'
AND identificacion_temporal LIKE '%-[0-9][0-9][0-9][0-9][0-9][0-9]')
)),
CONSTRAINT fk_pacientes_personas FOREIGN KEY (id) REFERENCES personas (id)
);
GO
CREATE UNIQUE NONCLUSTERED INDEX ix_pacientes_id_temporal
ON pacientes (identificacion_temporal)
WHERE identificacion_temporal IS NOT NULL;
GO
CREATE TABLE sedes
(
id UNIQUEIDENTIFIER PRIMARY KEY,
region NVARCHAR(50),
created_at DATETIME NOT NULL
CONSTRAINT df_sedes_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
CONSTRAINT fk_sedes_entidades FOREIGN KEY (id) REFERENCES entidades (id),
INDEX ix_sedes_region (region)
);
GO
CREATE TABLE doctores
(
id UNIQUEIDENTIFIER PRIMARY KEY
CONSTRAINT df_doctores_id DEFAULT NEWID(),
idoneidad NVARCHAR(20) NOT NULL,
categoria NVARCHAR(100),
sede UNIQUEIDENTIFIER,
created_at DATETIME NOT NULL
CONSTRAINT df_doctores_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
CONSTRAINT fk_doctores_personas FOREIGN KEY (id) REFERENCES personas (id),
CONSTRAINT fk_doctores_sedes FOREIGN KEY (sede) REFERENCES sedes (id),
INDEX ix_doctores_idoneidad (idoneidad)
);
GO
-- TODO crear tabla intermedia dosis_intervalos
-- TODO eliminar la relación vacuna fabricante a una vacuna por fabricante
CREATE TABLE vacunas
(
id UNIQUEIDENTIFIER PRIMARY KEY
CONSTRAINT df_vacunas_id DEFAULT NEWID(),
nombre NVARCHAR(100) NOT NULL,
--fabricante UNIQUEIDENTIFIER NOT NULL,
edad_minima_dias INT,
intervalo_dosis_1_2_dias INT,
dosis_maxima CHAR(2),
created_at DATETIME NOT NULL
CONSTRAINT df_vacunas_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
CONSTRAINT ck_vacunas_dosis_maxima CHECK (dosis_maxima IN ('1', '2', '3', 'R', 'R1', 'R2', 'P')),
CONSTRAINT ck_vacunas_edad_minima CHECK (edad_minima_dias >= 0),
--CONSTRAINT fk_vacunas_fabricantes FOREIGN KEY (fabricante) REFERENCES fabricantes (id) ON UPDATE CASCADE,
INDEX ix_vacunas_nombre (nombre)
);
GO
CREATE TABLE dosis
(
id UNIQUEIDENTIFIER PRIMARY KEY
CONSTRAINT df_dosis_id DEFAULT NEWID(),
paciente UNIQUEIDENTIFIER NOT NULL,
fecha_aplicacion DATETIME NOT NULL
CONSTRAINT df_dosis_aplicacion DEFAULT CURRENT_TIMESTAMP,
numero_dosis CHAR(2) NOT NULL,
vacuna UNIQUEIDENTIFIER NOT NULL,
sede UNIQUEIDENTIFIER NOT NULL,
doctor UNIQUEIDENTIFIER,
lote NVARCHAR(50),
created_at DATETIME NOT NULL
CONSTRAINT df_dosis_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
CONSTRAINT ck_dosis_numero_dosis CHECK (numero_dosis IN ('1', '2', '3', 'R', 'R1', 'R2', 'P')),
CONSTRAINT fk_dosis_pacientes FOREIGN KEY (paciente) REFERENCES pacientes (id),
CONSTRAINT fk_dosis_vacunas FOREIGN KEY (vacuna) REFERENCES vacunas (id) ON UPDATE CASCADE,
CONSTRAINT fk_dosis_sedes FOREIGN KEY (sede) REFERENCES sedes (id) ON UPDATE CASCADE
);
GO
CREATE TABLE fabricantes
(
id UNIQUEIDENTIFIER PRIMARY KEY,
licencia NVARCHAR(50) NOT NULL,
contacto_nombre NVARCHAR(100),
contacto_correo VARCHAR(254),
contacto_telefono VARCHAR(15),
created_at DATETIME NOT NULL
CONSTRAINT df_fabricantes_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
usuario UNIQUEIDENTIFIER,
CONSTRAINT ck_fabricantes_licencia CHECK (licencia LIKE '%/DNFD'),
CONSTRAINT ck_fabricantes_correo CHECK (contacto_correo IS NULL OR
(contacto_correo LIKE '%_@_%.__%' AND LEN(contacto_correo) >= 5)),
CONSTRAINT ck_fabricantes_telefono CHECK (contacto_telefono IS NULL OR
(contacto_telefono LIKE '+[0-9]%' AND
LEN(contacto_telefono) >= 5 AND
TRY_CAST(SUBSTRING(contacto_telefono, 2, LEN(contacto_telefono)) AS BIGINT) IS NOT NULL)),
CONSTRAINT fk_fabricantes_entidades FOREIGN KEY (id) REFERENCES entidades (id),
CONSTRAINT fk_fabricantes_usuarios FOREIGN KEY (usuario) REFERENCES usuarios (id) ON UPDATE CASCADE,
INDEX ix_fabricantes_licencia (licencia)
);
GO
CREATE UNIQUE NONCLUSTERED INDEX ix_fabricantes_usuario
ON fabricantes (usuario)
WHERE usuario IS NOT NULL;
GO
CREATE TABLE almacenes
(
id UNIQUEIDENTIFIER PRIMARY KEY,
encargado UNIQUEIDENTIFIER,
CONSTRAINT fk_almacenes_entidades FOREIGN KEY (id) REFERENCES entidades (id),
CONSTRAINT fk_almacenes_personas FOREIGN KEY (encargado) REFERENCES personas (id),
);
GO
CREATE TABLE almacenes_inventarios
(
almacen UNIQUEIDENTIFIER NOT NULL,
vacuna UNIQUEIDENTIFIER NOT NULL,
cantidad INT NOT NULL,
fecha_expiracion DATETIME NOT NULL,
lote NVARCHAR(50) NOT NULL,
fecha_recepcion DATETIME NOT NULL
CONSTRAINT df_almacenes_inventario_recepcion DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (almacen, vacuna),
CONSTRAINT ck_almacenes_inventarios_fecha_expiracion CHECK (fecha_expiracion > GETDATE()),
CONSTRAINT ck_almacenes_inventarios_cantidad CHECK (cantidad >= 0),
CONSTRAINT fk_almacenes_inventarios_almacenes FOREIGN KEY (almacen) REFERENCES almacenes (id),
CONSTRAINT fk_almacenes_inventarios_vacunas FOREIGN KEY (vacuna) REFERENCES vacunas (id)
);
GO
CREATE TABLE sedes_inventarios
(
sede UNIQUEIDENTIFIER NOT NULL,
vacuna UNIQUEIDENTIFIER NOT NULL,
cantidad INT NOT NULL,
fecha_expiracion DATETIME NOT NULL,
lote NVARCHAR(50) NOT NULL,
fecha_recepcion DATETIME NOT NULL
CONSTRAINT df_sedes_inventarios_recepcion DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (sede, vacuna),
CONSTRAINT ck_sedes_inventarios_fecha_expiracion CHECK (fecha_expiracion > GETDATE()),
CONSTRAINT ck_sedes_inventarios_cantidad CHECK (cantidad >= 0),
CONSTRAINT fk_sedes_inventarios_sedes FOREIGN KEY (sede) REFERENCES sedes (id),
CONSTRAINT fk_sedes_inventarios_vacunas FOREIGN KEY (vacuna) REFERENCES vacunas (id)
);
GO
CREATE TABLE distribuciones_vacunas
(
id UNIQUEIDENTIFIER PRIMARY KEY
CONSTRAINT df_distribuciones_id DEFAULT NEWID(),
almacen UNIQUEIDENTIFIER NOT NULL,
sede UNIQUEIDENTIFIER NOT NULL,
vacuna UNIQUEIDENTIFIER NOT NULL,
cantidad INT NOT NULL,
lote NVARCHAR(50) NOT NULL,
fecha_distribucion DATETIME NOT NULL
CONSTRAINT df_distribuciones_fecha_distribucion DEFAULT CURRENT_TIMESTAMP,
created_at DATETIME NOT NULL
CONSTRAINT df_distribuciones_created DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
CONSTRAINT ck_distribuciones_fecha_distribucion CHECK (fecha_distribucion <= GETDATE()),
CONSTRAINT fk_distribuciones_almacenes FOREIGN KEY (almacen) REFERENCES almacenes (id),
CONSTRAINT fk_distribuciones_sedes FOREIGN KEY (sede) REFERENCES sedes (id),
CONSTRAINT fk_distribuciones_vacunas FOREIGN KEY (vacuna) REFERENCES vacunas (id)
);
GO
CREATE TABLE fabricantes_vacunas
(
fabricante UNIQUEIDENTIFIER,
vacuna UNIQUEIDENTIFIER,
PRIMARY KEY (fabricante, vacuna),
CONSTRAINT fk_fabricantes_vacunas_fabricantes FOREIGN KEY (fabricante) REFERENCES fabricantes (id) ON UPDATE CASCADE,
CONSTRAINT fk_fabricantes_vacunas_vacunas FOREIGN KEY (vacuna) REFERENCES vacunas (id) ON DELETE CASCADE
);
GO
CREATE TABLE enfermedades
(
id INT PRIMARY KEY IDENTITY (0,1),
nombre NVARCHAR(100) NOT NULL,
nivel_gravedad NVARCHAR(50),
CONSTRAINT uq_enfermedades_nombre UNIQUE (nombre),
INDEX ix_enfermedades_nombre (nombre)
);
GO
CREATE TABLE sintomas
(
id INT PRIMARY KEY IDENTITY (0,1),
nombre NVARCHAR(50) NOT NULL,
CONSTRAINT uq_sintomas_nombre UNIQUE (nombre),
INDEX ix_sintomas_nombre (nombre)
);
GO
CREATE TABLE enfermedades_sintomas
(
enfermedad INT,
sintoma INT,
PRIMARY KEY (sintoma, enfermedad),
CONSTRAINT fk_enfermedades_sintomas_sintomas FOREIGN KEY (sintoma) REFERENCES sintomas (id) ON UPDATE CASCADE,
CONSTRAINT fk_enfermedades_sintomas_enfermedades FOREIGN KEY (enfermedad) REFERENCES enfermedades (id) ON UPDATE CASCADE
);
GO
CREATE TABLE vacunas_enfermedades
(
vacuna UNIQUEIDENTIFIER,
enfermedad INT,
PRIMARY KEY (vacuna, enfermedad),
CONSTRAINT fk_vacunas_enfermedades_vacunas FOREIGN KEY (vacuna) REFERENCES vacunas (id) ON DELETE CASCADE,
CONSTRAINT fk_vacunas_enfermedades_enfermedades FOREIGN KEY (enfermedad) REFERENCES enfermedades (id) ON DELETE CASCADE
);
GO
PRINT (N'Tablas terminadas');
GO
PRINT (N'Creando vistas');
GO
CREATE VIEW view_usuarios_detalles AS
SELECT u.id,
u.usuario,
pe.id AS 'id_persona',
pe.cedula,
pe.pasaporte,
pe.correo AS 'correo_persona',
pe.telefono AS 'telefono_persona',
e.id AS 'id_entidad',
e.correo AS 'correo_entidad',
e.telefono AS 'telefono_entidad',
p.identificacion_temporal,
doc.idoneidad,
f.licencia,
u.clave,
u.created_at,
u.updated_at,
u.last_used
FROM usuarios u
LEFT JOIN personas pe ON pe.usuario = u.id
LEFT JOIN fabricantes f ON u.id = f.usuario
LEFT JOIN entidades e ON e.id = f.id
LEFT JOIN pacientes p ON pe.id = p.id
LEFT JOIN doctores doc ON pe.id = doc.id
GO
CREATE VIEW view_pacientes_detalles AS
SELECT pe.cedula AS N'Cédula',
pe.pasaporte AS 'Pasaporte',
p.identificacion_temporal AS N'Identificación Temporal',
pe.nombre AS 'Nombre',
pe.apellido1 AS 'Primer Apellido',
pe.apellido2 AS 'Segundo Apellido',
pe.fecha_nacimiento AS 'Fecha de Nacimiento',
pe.fecha_nacimiento AS 'Edad',
pe.sexo AS 'Sexo',
pe.telefono AS N'Teléfono',
pe.correo AS N'Correo Electrónico',
d.direccion AS N'Dirección',
dd.nombre AS 'Distrito',
pp.nombre AS 'Provincia',
pe.estado,
p.created_at,
p.updated_at,
pe.usuario,
p.id,
d.id AS 'id_direccion',
dd.id AS 'id_distrito',
pp.id AS 'id_provincia'
FROM personas pe
LEFT JOIN pacientes p ON p.id = pe.id
LEFT JOIN direcciones d ON pe.direccion = d.id
LEFT JOIN distritos dd ON d.distrito = dd.id
LEFT JOIN provincias pp ON dd.provincia = pp.id;
GO
CREATE VIEW view_fabricantes_detalles AS
SELECT e.nombre AS 'Nombre',
f.licencia AS 'Licencia Autorizada',
e.telefono AS 'Teléfono',
e.correo AS 'Correo Electrónico',
f.contacto_nombre AS 'Nombre Contacto',
f.contacto_correo AS 'Correo Electrónico Contacto',
f.contacto_telefono AS 'Teléfono Contacto',
d.direccion AS N'Dirección',
dd.nombre AS 'Distrito',
pp.nombre AS 'Provincia',
e.estado,
f.created_at,
f.updated_at,
f.usuario,
f.id,
d.id AS 'id_direccion',
dd.id AS 'id_distrito',
pp.id AS 'id_provincia'
FROM entidades e
LEFT JOIN fabricantes f ON f.id = e.id
LEFT JOIN direcciones d ON e.direccion = d.id
LEFT JOIN distritos dd ON d.distrito = dd.id
LEFT JOIN provincias pp ON dd.provincia = pp.id;
GO
CREATE VIEW view_pacientes_usuarios AS
SELECT pe.cedula AS N'Cédula Paciente',
pe.pasaporte AS 'Pasaporte Paciente',
p.identificacion_temporal AS N'Identificación Temporal',
pe.nombre AS 'Nombre',
pe.apellido1 AS 'Primer Apellido',
pe.apellido2 AS 'Segundo Apellido',
pe.fecha_nacimiento AS 'Fecha de Nacimiento Paciente',
pe.fecha_nacimiento AS 'Edad',
pe.sexo AS 'Sexo',
pe.telefono AS N'Teléfono Paciente',
pe.correo AS N'Correo Electrónico Paciente',
u.usuario AS 'Usuario',
pe.estado AS 'estado_paciente',
p.created_at AS 'created_at_paciente',
p.updated_at AS 'updated_at_paciente',
p.id,
u.created_at AS 'created_at_usuario',
u.updated_at AS 'updated_at_usuario',
u.last_used,
u.id AS 'id_usuario'
FROM personas pe
LEFT JOIN pacientes p ON p.id = pe.id
LEFT JOIN usuarios u ON pe.usuario = u.id;
GO
CREATE VIEW view_enfermedades_sintomas AS
SELECT e.nombre AS 'Enfermedad',
e.nivel_gravedad AS 'Nivel de Gravedad',
STRING_AGG(s.nombre, ', ') AS N'Síntomas',
e.id,
STRING_AGG(s.id, ', ') AS 'ids_sintomas'
FROM enfermedades e
LEFT JOIN enfermedades_sintomas es ON e.id = es.enfermedad
LEFT JOIN sintomas s ON es.sintoma = s.id
GROUP BY e.nombre, e.nivel_gravedad, e.id;
GO
CREATE VIEW view_vacunas_enfermedades AS
SELECT v.nombre AS 'Nombre Vacuna',
v.edad_minima_dias AS 'Edad mínima Recomendada en Meses',
v.intervalo_dosis_1_2_dias 'Intervalo entre Dosis 1 y 2 Recomendado en Meses',
v.dosis_maxima AS 'Dosis Máxima Recomendada',
STRING_AGG(e.nombre, ', ') AS 'Enfermedades Prevenidas',
STRING_AGG(e.nivel_gravedad, ', ') AS 'Niveles de Gravedad Enfermedades',
v.id,
v.created_at,
v.updated_at,
e.id AS 'id_enfermedad'
FROM vacunas v
LEFT JOIN vacunas_enfermedades ve ON v.id = ve.vacuna
LEFT JOIN enfermedades e ON ve.enfermedad = e.id
GROUP BY v.nombre, v.edad_minima_dias, v.intervalo_dosis_1_2_dias, v.dosis_maxima, v.id, v.created_at, v.updated_at,
e.id
GO
CREATE VIEW view_roles_permisos AS
SELECT r.nombre AS 'Nombre Rol',
r.descripcion AS N'Descripción Rol',
STRING_AGG(p.nombre, ', ') AS 'Nombres Permisos',
r.created_at,
r.updated_at,
r.id,
STRING_AGG(p.id, ', ') AS 'ids_permisos'
FROM roles r
LEFT JOIN roles_permisos rp ON r.id = rp.rol
LEFT JOIN permisos p ON rp.permiso = p.id
GROUP BY r.nombre, r.descripcion, r.id, r.created_at, r.updated_at;
GO
CREATE VIEW view_roles_usuarios AS
SELECT r.nombre AS 'Nombre Rol',
STRING_AGG(CAST(u.id AS VARCHAR(36)), ', ') AS 'ids_usuarios',
STRING_AGG(ur.created_at, ', ') AS 'Rol Otorgado desde',
r.id
FROM roles r
LEFT JOIN usuarios_roles ur ON r.id = ur.rol
INNER JOIN usuarios u ON ur.usuario = u.id
GROUP BY r.nombre, r.id;
GO
CREATE VIEW view_direcciones_detalles AS
SELECT d.direccion AS 'Dirección',
dd.nombre AS 'Distrito',
pp.nombre AS 'Provincia',
d.id,
dd.id AS 'id_distrito',
pp.id AS 'id_provincia'
FROM direcciones d
LEFT JOIN distritos dd ON d.distrito = dd.id
LEFT JOIN provincias pp ON dd.provincia = pp.id;
GO
CREATE VIEW view_vacunas_fabricantes AS
SELECT v.nombre AS 'Nombre Vacuna',
STRING_AGG(e.nombre, ', ') AS 'Fabricantes',
v.id,
STRING_AGG(CAST(f.id AS VARCHAR(36)), ', ') AS 'ids_fabricante'
FROM vacunas v
INNER JOIN fabricantes_vacunas fv ON v.id = fv.vacuna
LEFT JOIN fabricantes f ON fv.fabricante = f.id
LEFT JOIN entidades e ON f.id = e.id
GROUP BY v.nombre, v.id
GO
CREATE VIEW view_pacientes_vacunas_enfermedades AS
SELECT v.nombre AS 'Nombre Vacuna',
d.numero_dosis AS N'Número de dosis',
STRING_AGG(e.nombre, ', ') AS N'Enfermedades Prevenidas',
v.edad_minima_dias AS N'Edad Mínima Recomendada en Días',
d.fecha_aplicacion AS N'Fecha de Aplicación',
v.intervalo_dosis_1_2_dias AS N'Intervalo Recomendado entre Dosis 1 y 2 en Días',
DATEDIFF(DAY, d.fecha_aplicacion,
(SELECT MAX(d2.fecha_aplicacion)
FROM dosis d2
WHERE d2.paciente = p.id
AND d2.vacuna = d.vacuna
AND d2.numero_dosis > d.numero_dosis))
AS N'Intervalo Real en Días',
ee.nombre AS 'Sede',
ee.dependencia AS 'Dependencia',
p.id,
v.id AS 'id_vacuna',
ee.id AS 'id_sede',
d.id AS 'id_dosis',
STRING_AGG(e.id, ', ') AS 'ids_enfermedades'
FROM pacientes p
JOIN dosis d ON p.id = d.paciente
JOIN vacunas v ON d.vacuna = v.id
LEFT JOIN vacunas_enfermedades ve ON v.id = ve.vacuna
LEFT JOIN enfermedades e ON ve.enfermedad = e.id
LEFT JOIN sedes s ON d.sede = s.id
LEFT JOIN entidades ee ON s.id = ee.id
GROUP BY p.id,
v.nombre, v.edad_minima_dias, v.intervalo_dosis_1_2_dias,
ee.nombre, ee.dependencia, ee.id,
v.id,
d.id, d.vacuna, d.fecha_aplicacion, d.numero_dosis;
GO
CREATE VIEW view_distribuciones_almacenes_sedes_vacunas_fabricantes AS
SELECT ae.nombre AS N'Nombre Almacén',
ae.dependencia AS N'Dependencia Almacén',
se.nombre AS 'Nombre Sede',
se.dependencia AS 'Dependencia Sede',
v.nombre AS 'Nombre Vacuna',
fe.nombre AS 'Nombre Fabricante',
d.cantidad AS 'Cantidad',
d.lote AS 'Lote',
d.fecha_distribucion AS 'Fecha de Distribución',
d.created_at,
d.updated_at,
d.id,
a.id AS 'id_almacen',
s.id AS 'id_sede',
v.id AS 'id_vacuna',
f.id AS 'id_fabricante'
FROM distribuciones_vacunas d
LEFT JOIN almacenes a ON d.almacen = a.id
LEFT JOIN entidades ae ON a.id = ae.id
LEFT JOIN sedes s ON d.sede = s.id
LEFT JOIN entidades se ON s.id = se.id
LEFT JOIN vacunas v ON d.vacuna = v.id
LEFT JOIN fabricantes_vacunas fv ON v.id = fv.vacuna
LEFT JOIN fabricantes f ON fv.fabricante = f.id
LEFT JOIN entidades fe ON f.id = fe.id;
GO
CREATE VIEW view_almacenes_inventarios_vacunas_fabricantes AS
SELECT ae.nombre AS N'Nombre Almacén',
ae.dependencia AS N'Dependencia Almacén',
v.nombre AS 'Nombre Vacuna',
fe.nombre AS 'Nombre Fabricante',
ai.cantidad AS 'Cantidad Disponible',
ai.fecha_expiracion AS 'Fecha de Expiración',
ai.lote AS 'Lote',
ai.fecha_recepcion AS 'Fecha de Recepción',
a.id,
v.id AS 'id_vacuna',
f.id AS 'id_fabricante'
FROM almacenes_inventarios ai
LEFT JOIN almacenes a ON ai.almacen = a.id
LEFT JOIN entidades ae ON a.id = ae.id
LEFT JOIN vacunas v ON ai.vacuna = v.id
LEFT JOIN fabricantes_vacunas fv ON v.id = fv.vacuna
LEFT JOIN fabricantes f ON fv.fabricante = f.id
LEFT JOIN entidades fe ON f.id = fe.id;
GO
CREATE VIEW view_sedes_inventarios_vacunas_fabricantes AS
SELECT se.nombre AS 'Nombre Sede',
se.dependencia AS 'Dependencia Sede',
v.nombre AS 'Nombre Vacuna',
fe.nombre AS 'Nombre Fabricante',
si.cantidad AS 'Cantidad Disponible',
si.fecha_expiracion AS N'Fecha de Expiración',
si.lote AS 'Lote',
si.fecha_recepcion AS N'Fecha de Recepción',
s.id,
v.id AS 'id_vacuna',
f.id AS 'id_fabricante'
FROM sedes_inventarios si
LEFT JOIN sedes s ON si.sede = s.id
LEFT JOIN entidades se ON s.id = se.id
LEFT JOIN vacunas v ON si.vacuna = v.id
LEFT JOIN fabricantes_vacunas fv ON v.id = fv.vacuna
LEFT JOIN fabricantes f ON fv.fabricante = f.id
LEFT JOIN entidades fe ON f.id = fe.id;
GO
CREATE VIEW view_doctores_sedes AS
SELECT doc.idoneidad AS 'Idoneidad',
pe.nombre AS 'Nombre Doctor',
pe.apellido1 AS 'Primer Apellido',
doc.categoria AS 'Categoría del Doctor',
se.nombre AS 'Nombre Sede',
se.dependencia AS 'Dependencia Sede',
s.region AS 'Región de la Sede',
d.direccion AS 'Dirección Sede',
dd.nombre AS 'Distrito Sede',
pp.nombre AS 'Provincia Sede'
FROM doctores doc
LEFT JOIN personas pe ON doc.id = pe.id
LEFT JOIN sedes s ON doc.sede = s.id
LEFT JOIN entidades se ON s.id = se.id
LEFT JOIN direcciones d ON pe.direccion = d.id
LEFT JOIN distritos dd ON d.distrito = dd.id
LEFT JOIN provincias pp ON dd.provincia = pp.id;
GO
PRINT (N'Creando triggers');
GO
-- Triggers
-- Trigger para asignar automáticamente la región a las sedes cuando coincide con la provincia y/o distrito
CREATE TRIGGER tr_sedes_insert_region
ON sedes
AFTER INSERT, UPDATE
AS
BEGIN
IF TRIGGER_NESTLEVEL() > 1
RETURN
BEGIN TRY
UPDATE S
SET region =
CASE
WHEN P.id = 1 THEN 'Bocas del Toro'
WHEN P.id = 2 THEN N'Coclé'
WHEN P.id = 3 THEN N'Colón'
WHEN P.id = 4 THEN N'Chiriquí'
WHEN P.id = 5 THEN N'Darién y la comarca Embera Waunán y Wargandí'
WHEN P.id = 6 THEN 'Herrera'
WHEN P.id = 7 THEN 'Los Santos'
WHEN P.id = 8 AND D.distrito = 53 THEN 'San Miguelito'
WHEN P.id = 8 AND D.distrito <> 53 THEN N'Panamá Norte/Este/Metro'
WHEN P.id = 9 THEN 'Veraguas'
WHEN P.id = 10 THEN 'Kuna Yala'
WHEN P.id = 11 THEN N'Darién y la comarca Embera Waunán y Wargandí'
WHEN P.id = 12 THEN N'Ngabe Buglé'
WHEN P.id = 13 AND D.distrito <> 79 THEN N'Panamá Oeste'
WHEN P.id = 13 AND D.distrito = 79 THEN N'Arraiján'
WHEN P.id = 16 THEN N'Darién y la comarca Embera Waunán y Wargandí'
ELSE 'Por registrar'
END
FROM sedes S
INNER JOIN inserted I ON S.id = I.id
INNER JOIN entidades PE ON S.id = PE.id
INNER JOIN direcciones D ON PE.direccion = D.id
INNER JOIN distritos DD ON D.distrito = DD.id
INNER JOIN provincias P ON DD.provincia = P.id
END TRY
BEGIN CATCH
THROW;
END CATCH
END;
GO
-- trigger para mantener registro de cambios
CREATE TRIGGER tr_usuarios_updated
ON usuarios
AFTER UPDATE
AS
BEGIN
IF TRIGGER_NESTLEVEL() > 1
RETURN
BEGIN TRY
UPDATE usuarios
SET updated_at = CURRENT_TIMESTAMP
WHERE id = (SELECT id FROM inserted)
END TRY
BEGIN CATCH
THROW;
END CATCH
END
GO
CREATE TRIGGER tr_doctores_updated
ON doctores
AFTER UPDATE
AS
BEGIN
IF TRIGGER_NESTLEVEL() > 1
RETURN
BEGIN TRY
UPDATE doctores
SET updated_at = CURRENT_TIMESTAMP