-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSQLAdvanceQuery2.sql
More file actions
800 lines (666 loc) · 18.3 KB
/
SQLAdvanceQuery2.sql
File metadata and controls
800 lines (666 loc) · 18.3 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
/*
# 1. Operaciones SQL
*/
USE DB_JP_SQL_BASICO;
SELECT * FROM SCHOOL;
-- __________________________
USE DB_JP_SQL_BASICO
SELECT
*
FROM
SCHOOL
WHERE NUM_OF_STUDENTS IS NULL
-- __________________
USE DB_JP_SQL_BASICO
SELECT
*
FROM
SCHOOL
WHERE NUM_OF_STUDENTS IS NOT NULL
-- ______________________
USE DB_JP_SQL_BASICO
SELECT
NAME, ACRONYM
FROM
SCHOOL
WHERE
NUM_OF_STUDENTS IS NOT NULL
AND
NAME LIKE 'C%a' -- LIKE is Regex but powerless
USE DB_JP_SQL_BASICO
SELECT
NAME, ACRONYM, NUM_OF_STUDENTS
FROM
SCHOOL
WHERE
NUM_OF_STUDENTS IS NOT NULL
AND
(
NAME LIKE 'cien%'
OR
NAME LIKE '%admin%'
)
ORDER BY
NUM_OF_STUDENTS, NAME
/*
# 2. Nested query
*/
USE DB_JP_SQL_BASICO
SELECT * FROM COURSE
SELECT * FROM [GROUP]
INSERT INTO
COURSE (ACRONYM, NAME, CREDITS)
VALUES
('CS101', 'Intro to Computer Science', 3),
('MA101', 'Calculus I', 4),
('PHY101', 'Physics I', 4),
('HT101', 'History of World Civilization', 3),
('ENG101', 'English Composition', 3)
INSERT INTO
[GROUP] (NUMBER, SEMESTER, YEAR, ACRONYM)
VALUES
(1, 1, 2023, 'CS101'),
(3, 1, 2023, 'PHY101'),
(4, 1, 2023, 'HT101'),
(6, 2, 2023, 'CS101'),
(8, 2, 2023, 'PHY101'),
(9, 2, 2023, 'HT101'),
(10, 2, 2023, 'ENG101'),
(13, 1, 2024, 'PHY101'),
(14, 1, 2024, 'HT101'),
(15, 1, 2024, 'ENG101')
-- ______________________________
SELECT
NAME, CREDITS
FROM
COURSE
WHERE ACRONYM IN -- We search ACRONYM inside of the thins of the scope
(
SELECT
ACRONYM
FROM
[GROUP]
WHERE
[YEAR] = 2023 AND SEMESTER = 1
)
-- _______________________________
SELECT
ACRONYM
FROM
COURSE
WHERE NOT EXISTS
(
SELECT
*
FROM
[GROUP]
WHERE
[GROUP].ACRONYM = [COURSE].ACRONYM
AND
[GROUP].SEMESTER = 2
AND
[GROUP].[YEAR] = 2023
)
-- ____________________________
-- EXIST y NOT EXIST review if the SELECT clause match with the WHERE anid.
SELECT
ACRONYM AS ACR, NAME as CourseName
FROM
COURSE AS C
WHERE EXISTS /*NOT EXISTS*/
(
SELECT
*
FROM
[GROUP] as G
WHERE
C.ACRONYM = G.ACRONYM
AND
G.SEMESTER = 2
AND
G.YEAR = 2023
)
/*
# 3. Join
*/
/*ALL Combinatios
AxB = producto cruz de ambos conjuntos
*/
use DB_JP_SQL_BASICO;
SELECT * FROM [GROUP], COURSE
-- _______________________
USE DB_JP_SQL_BASICO
-- Intersection of same attr A&B
SELECT
C.NAME, C.CREDITS, G.NUMBER, G.SEMESTER AS SEM, G.[YEAR]
FROM
COURSE AS C
INNER JOIN -- INNER is not necessary
[GROUP] AS G
ON -- Related PK with FK
C.ACRONYM = G.ACRONYM
ORDER BY
C.NAME, G.NUMBER, G.SEMESTER, G.[YEAR]
-- _______________________
USE DB_JP_SQL_BASICO
-- A - B
SELECT
C.ACRONYM, C.NAME, C.CREDITS, G.NUMBER, G.SEMESTER, G.[YEAR]
FROM
COURSE AS C -- A
LEFT JOIN
[GROUP] AS G -- B
ON
C.ACRONYM = G.ACRONYM
WHERE -- If we want the Intersection (A-B+A&B) Erase this where
G.ACRONYM IS NULL
ORDER BY
G.NUMBER, G.SEMESTER, G.[YEAR]
-- _______________________
USE DB_JP_SQL_BASICO
-- The base query is bad 'cause we define before GROUP dependent of COURSE
-- B - A
SELECT
C.NAME, C.CREDITS, G.NUMBER, G.SEMESTER, G.[YEAR]
FROM
COURSE AS C
RIGHT JOIN
[GROUP] AS G
ON
C.ACRONYM = G.ACRONYM
WHERE -- If we erase this is B - A & B&A
C.ACRONYM IS NULL
ORDER BY
G.NUMBER, G.SEMESTER, G.[YEAR]
-- ________________
USE DB_JP_SQL_BASICO
SELECT
C.NAME, C.CREDITS, G.NUMBER, G.SEMESTER, G.[YEAR]
FROM
COURSE AS C
FULL OUTER JOIN
[GROUP] AS G
ON
C.ACRONYM = G.ACRONYM
ORDER BY
G.NUMBER, G.SEMESTER, G.[YEAR]
-- _______________________
USE DB_JP_SQL_BASICO
SELECT
C.NAME, C.CREDITS, G.NUMBER, G.SEMESTER, G.[YEAR]
FROM
COURSE AS C
FULL OUTER JOIN
[GROUP] AS G
ON
C.ACRONYM = G.ACRONYM
WHERE
C.ACRONYM IS NULL OR G.ACRONYM IS NULL
ORDER BY
G.NUMBER, G.SEMESTER, G.[YEAR]
/*
# 4. Grouping and aggregation
*/
SELECT
ACRONYM, NUMBER, COUNT(*) AS ACR_COUNT
FROM
[GROUP]
GROUP BY ACRONYM,NUMBER
-- __________________
SELECT
ACRONYM,
COUNT(*) AS ACR_COUNT,
AVG (CREDITS) AS ACR_AVG,
MAX(CREDITS) AS ACR_MAX,
MIN(CREDITS) AS ACR_MIN
FROM
COURSE
GROUP BY
ACRONYM
-- ___________________ The class finish here.
-- Here init with Having clause, that filter on Grouped attr
SELECT
ACRONYM,
COUNT(*) COURSE_COUNT,
AVG (CREDITS) AS AVG_CREDITS
FROM
COURSE
GROUP BY
ACRONYM
HAVING
AVG (CREDITS) > 3;
-- ________________ Update a table Schema
ALTER TABLE
INSTRUCTOR
ADD
NAME VARCHAR(255) NULL
-- ________________ add Names and IDs cause are the PK
INSERT INTO
INSTRUCTOR (NAME)
VALUES
('Joe Doe'),
('Mary Doe'),
('Elle Doe')
-- Try to insert that object into IMPARTS table.
INSERT INTO
IMPARTS
VALUES
(1,10,2,2023,'ENG101')
-- How much courses Impart each Instructor.
SELECT
I.NAME AS I_NAME,
COUNT(*) AS COUNT_G
FROM
INSTRUCTOR AS I
-- LEFT JOIN
INNER JOIN
IMPARTS AS IM
ON
I.ID = IM.ID
GROUP BY
I.NAME
/*
## **5\. Triggers**
DML Triggers are fired as a response to dml statements (**insert, update or delete**).
A dml trigger can be created to address one or more dml events for a single table or view.
This means that a single dml trigger can handle inserting, updating and deleting records
from a specific table or view, but it can only handle data being changed on that single table or view.
*/
USE DB_JP_SQL_BASICO
SELECT * FROM SCHOOL;
SELECT * FROM COURSE;
SELECT * FROM [GROUP];
SELECT * FROM TAKES
-- Alter table course to add new attr
ALTER TABLE
COURSE
ADD
AREA_ACRONYM CHAR(6) NULL
CONSTRAINT FK_SCHOOL FOREIGN KEY (AREA_ACRONYM) REFERENCES SCHOOL(ACRONYM)
-- Set values to new relation with SCHOOL
UPDATE [COURSE] SET AREA_ACRONYM = 'EMat' WHERE ACRONYM = 'MA101';
UPDATE [COURSE] SET AREA_ACRONYM = 'EAT' WHERE ACRONYM = 'HT101';
UPDATE [COURSE] SET AREA_ACRONYM = 'ECCI' WHERE ACRONYM = 'CS101';
UPDATE [COURSE] SET AREA_ACRONYM = 'ELM' WHERE ACRONYM = 'ENG101';
UPDATE [COURSE] SET AREA_ACRONYM = 'ECCI' WHERE ACRONYM = 'PHY101';
/*
-- If we update on TAKES updates students number in SCHOOL
*/
CREATE TRIGGER
UPDATE_STUDENTS_NUMBER
ON
TAKES -- Here we define the table that will be trigger
AFTER INSERT AS -- Here we define the event that will trigger the trigger(INSERT)
BEGIN -- Open a new code block (optional)
UPDATE
SCHOOL
SET
NUM_OF_STUDENTS = NUM_OF_STUDENTS +
T.GCOUNT FROM
(
SELECT
C.AREA_ACRONYM, COUNT(AREA_ACRONYM) as GCOUNT
FROM
inserted AS NEW_TAKES -- "inserted" is the temp table that have the new values do update
JOIN
[GROUP] AS G
ON
NEW_TAKES.ACRONYM = G.ACRONYM AND
NEW_TAKES.NUMBER = G.NUMBER AND
NEW_TAKES.SEMESTER = G.SEMESTER AND
NEW_TAKES.[YEAR] = G.[YEAR]
JOIN
COURSE AS C
ON
C.ACRONYM = G.ACRONYM
GROUP BY C.AREA_ACRONYM
) AS T -- New local variable as table a.k.a query result
WHERE
SCHOOL.ACRONYM = T.AREA_ACRONYM
END -- Close the code block
--______________________________________________
/*
At this point if STUDENT is empty, when we add a new student, the trigger will
wont work, cause the table is empty. So we need to add a new student to test the trigger.
If we add a new student, the trigger in student not work, cause the trigger is in TAKES.
*/
SELECT * FROM STUDENT
INSERT INTO
STUDENT
VALUES
('jose@email.com','Jose','Ramirez','B65728',NULL),
('petter@email.com','Petter','Ramirez','B65729',NULL)
('jose@email.com','Jose','Ramirez','B65728',NULL),
('petter@email.com','Petter','Ramirez','B65729',NULL)
SELECT * FROM TAKES
/*
Esto cambia el número de estudiantes en el curso CS101,
o sea va a activar al trigger de arriba aumentando el constador
de los estudiantes de SCHOOL de la escuela de compu.
*/
INSERT INTO
TAKES
VALUES
('jose@email.com',1,1,2023,'CS101'),
('petter@email.com',6,2,2023,'CS101')
/*
En este caso, el trigger va a hacer dos cosas:
1. Aumentar el contador de estudiantes en la escuela de compu
2. Disminuir el contador de estudiantes en la escuela de compu
Porque tiene propiedades ON INSERT, DELETE
PERO estamos redundando el código, podemos hacerlo con otra técnica más
eficiente.
*/
ALTER TRIGGER UPDATE_STUDENTS_NUMBER -- ALTER moadifica el trigger
ON
TAKES
AFTER INSERT, DELETE
AS
BEGIN
/*Insert*/
UPDATE
SCHOOL
SET
NUM_OF_STUDENTS = NUM_OF_STUDENTS +
T.GCOUNT FROM
(
SELECT
C.AREA_ACRONYM, COUNT(AREA_ACRONYM) as GCOUNT
FROM
inserted AS NEW_TAKES /*inserted, deleted, updated*/
JOIN
[GROUP] AS G
ON
NEW_TAKES.ACRONYM = G.ACRONYM AND
NEW_TAKES.NUMBER = G.NUMBER AND
NEW_TAKES.SEMESTER = G.SEMESTER AND
NEW_TAKES.[YEAR] = G.[YEAR]
JOIN
COURSE AS C
ON
C.ACRONYM = G.ACRONYM
GROUP BY C.AREA_ACRONYM
) AS T
WHERE
SCHOOL.ACRONYM = T.AREA_ACRONYM
/*Delete*/
UPDATE
SCHOOL
SET
NUM_OF_STUDENTS = NUM_OF_STUDENTS -
T.GCOUNT FROM
(
SELECT
C.AREA_ACRONYM, COUNT(AREA_ACRONYM) as GCOUNT
FROM
deleted AS DELETED_TAKES /*inserted, deleted, updated*/
JOIN
[GROUP] AS G
ON
DELETED_TAKES.ACRONYM = G.ACRONYM AND
DELETED_TAKES.NUMBER = G.NUMBER AND
DELETED_TAKES.SEMESTER = G.SEMESTER AND
DELETED_TAKES.[YEAR] = G.[YEAR]
JOIN
COURSE AS C
ON
C.ACRONYM = G.ACRONYM
GROUP BY C.AREA_ACRONYM
) AS T
WHERE
SCHOOL.ACRONYM = T.AREA_ACRONYM
END
-----------------------
-- Se borra takes para probar el nuevo trigger
SELECT * FROM TAKES
SELECT * FROM SCHOOL
DELETE FROM TAKES -- Aquí se le borran los dos estudiantes de TAKES
-- O sea, quita dos estudiantes de la ECCI en SCHOOL
-----------------------
/*
# 6. Views
*/
USE DB_JP_SQL_BASICO
CREATE VIEW FULL_STUDENT_BOARD AS
SELECT
ST.FIRST_NAME,
ST.LAST_NAME,
T.EMAIL,
T.NUMBER,
T.SEMESTER,
T.[YEAR],
G.ACRONYM,
C.NAME,
C.AREA_ACRONYM
FROM
TAKES AS T
JOIN
[GROUP] AS G
ON
T.ACRONYM = G.ACRONYM AND
T.NUMBER = G.NUMBER AND
T.SEMESTER = G.SEMESTER AND
T.[YEAR] = G.[YEAR]
JOIN
COURSE AS C
ON
C.ACRONYM = G.ACRONYM
JOIN
STUDENT AS ST
ON
ST.EMAIL = T.EMAIL
/* --------------
Aquí nosotros llamamos al método que creó la view
---------------*/
SELECT * FROM FULL_STUDENT_BOARD
/* ---------------------------------------------------------------------------------
## **7\. Stored procedures**
In SQL Server, a procedure is a stored program that you can pass parameters into.
It does not return a value like a function does.
However, it can return a success/failure status to the procedure that called it.
*/
-- Declara la función que nos devuelve el Acronimo de un curso.
CREATE PROCEDURE GetCourseName (
@ACRONYM CHAR(6) -- Input parameter
)
AS BEGIN
SELECT NAME
FROM COURSE
WHERE ACRONYM = @ACRONYM
END
-- Ejecuta la función declarada
EXECUTE GetCourseName @ACRONYM = 'CS101';
/*
Store procedure with no return, but output parameters
*/
CREATE PROCEDURE GetEmptySchoolsCount (
@PEmptySchoolsCount INT OUTPUT
)
AS
BEGIN
SELECT
@PEmptySchoolsCount = COUNT(*)
FROM
SCHOOL
WHERE NUM_OF_STUDENTS = 0
END
/*
We can create/change variables in SQL
*/
DECLARE @EmptySchoolsCount INT;
EXEC GetEmptySchoolsCount @PEmptySchoolsCount = @EmptySchoolsCount OUTPUT;
PRINT 'Schools with zero students: ' + CONVERT(VARCHAR(10),@EmptySchoolsCount)
SET @EmptySchoolsCount = @EmptySchoolsCount * 2
PRINT 'Schools with zero students X 2: ' + CONVERT(VARCHAR(10),@EmptySchoolsCount)
/*
## 8. User defined functions
1. User-defined functions can't be used to perform actions that
modify the database state.
2. User-defined functions can't contain an OUTPUT INTO clause
that has a table as its target.
3. User-defined functions can't return multiple result sets.
Use a stored procedure if you need to return multiple result sets.
*/
CREATE FUNCTION GetTotalUniversityStudents(
@SchoolPattern VARCHAR(10) -- Variable to search
)
RETURNS INT /*Return type must be specified. This is an scalar function*/
AS
BEGIN
-- Return variable
DECLARE @OutStudentsCount INT
IF @SchoolPattern IS NOT NULL -- Si no es nulo suma todos los estudiantes de las escuelas que cumplan con el patrón
BEGIN -- Scope del if
SELECT
@OutStudentsCount = SUM(NUM_OF_STUDENTS)
FROM
SCHOOL
WHERE
NAME LIKE @SchoolPattern
END
ELSE -- Si es nulo suma todos los estudiantes de todas las escuelas
BEGIN
SELECT
@OutStudentsCount = SUM(NUM_OF_STUDENTS)
FROM
SCHOOL
END
-- Esto es redundante, pero es un ejemplo de cómo se puede hacer
IF @OutStudentsCount IS NULL -- Si no hay estudiantes, devuelve 0
BEGIN
SET @OutStudentsCount = 0
END
RETURN @OutStudentsCount
END
/*
Tengo que llama a ejecutar la función de manera que todo haga match.
*/
DECLARE @SchoolPattern VARCHAR(100)
DECLARE @Result int
SET @SchoolPattern = '%a%'
EXEC @Result = GetTotalUniversityStudents @SchoolPattern = @SchoolPattern
PRINT @Result
------------------------------------------------------------
/*
Función para obtener los estudiantes de una escuela
CREATE OR ALTER nos permite modificar la función sin tener que borrarla y volverla a crear
Este devuelve una tabla.
*/
USE DB_JP_SQL_BASICO
CREATE OR ALTER FUNCTION GetSchoolStudents( /*https://support.microsoft.com/en-gb/topic/kb3190548-update-introduces-create-or-alter-transact-sql-statement-in-sql-server-2016-fd0596f3-9098-329c-a7a5-2e18f29ad1d4*/
@SchoolPattern VARCHAR(10)
)
RETURNS TABLE
AS
RETURN (
SELECT
S.NAME,
S.ACRONYM AS SCHOOL_ACR,
C.ACRONYM AS COURSE_ACR,
G.NUMBER,
G.SEMESTER,
G.[YEAR],
T.EMAIL
FROM
SCHOOL AS S
INNER JOIN
COURSE AS C
ON
S.ACRONYM = C.AREA_ACRONYM
INNER JOIN
[GROUP] AS G
ON
G.ACRONYM = C.ACRONYM
INNER JOIN
TAKES AS T
ON
T.ACRONYM = G.ACRONYM AND
T.NUMBER = G.NUMBER AND
T.SEMESTER = G.SEMESTER AND
T.[YEAR] = G.[YEAR]
WHERE
S.NAME LIKE @SchoolPattern
)
/*
Create an variable of table type to receive a table of the function.
*/
DECLARE @TMP_TABLE TABLE (
NAME VARCHAR(255),
SCHOOL_ACR CHAR(6),
COURSE_ACR CHAR(6),
NUMBER SMALLINT,
SEMESTER SMALLINT,
YEAR SMALLINT,
EMAIL VARCHAR(255)
)
-- Populate a table variable. Will make more sense once we are in the relational algebra section. Take it easy :)
INSERT INTO
@TMP_TABLE
SELECT * FROM GetSchoolStudents('%A%')
-- Print the table variable
SELECT * FROM @TMP_TABLE;
------------------------------------------------ Run all previous to get it work
/*
# 9\. Cursor
https://learn.microsoft.com/en-us/sql/relational-databases/cursors?view=sql-server-ver16#type-of-cursors
Cursors are used to retrieve data **row-by-row**
from a result set and perform operations on each row.
Generally speaking, set-based operations (which operate on all
the rows in the result set at once) are faster and more efficient in SQL Server,
so it's usually better to **avoid** using cursors whenever possible
## Use Cases
1\. Perform complex **computations or transformations** on each row of a result
set that cannot easily be expressed in a single SQL statement
2\. Process or handle one row at a time.
This could be necessary for calling a **stored procedure** for each row
3\. Process rows in a specific order, and each row's processing
may depend on the previous rows
## Considerations
1. Cursors can have a significant performance impact because they process rows individually, **leading to more reads**, more **locking**, and more **memory usage**
*/
USE DB_JP_SQL_BASICO
DECLARE @S_NAME VARCHAR(255), @NUM_OF_STUDENTS INT
-- LOCAL: Solo visible para este batch de instrucciones y no para los eventos desencadenadores
-- FAST_FORWARD: Solo se desplaza hacia adelante, de primera fila a ultima
/*
Declaramos un cursor que primero va a ser busqueda LOCAL y despu�s FAST_FORWARD.
FOR definidos en que queremos iterar
Con OPEN ponemos a funcionar el CURSOR
*/
DECLARE ROW_CURSOR CURSOR LOCAL FAST_FORWARD FOR -- Hay varios tipos de cursores dependiento del Data Source
(SELECT NAME, NUM_OF_STUDENTS FROM SCHOOL)
-- Siempre se debe abrir el cursor primero
OPEN ROW_CURSOR
FETCH NEXT FROM ROW_CURSOR INTO @S_NAME, @NUM_OF_STUDENTS
-- Varibale global siempre, cuando no hay mas filas cambia a 1
WHILE @@FETCH_STATUS = 0 -- @@ variables din�micas del sistema
BEGIN
PRINT CONCAT('The school name is: ',@S_NAME,'. It has ', @NUM_OF_STUDENTS, ' students')
-- mover cursor a la siguiente fila
FETCH NEXT FROM ROW_CURSOR INTO @S_NAME, @NUM_OF_STUDENTS
END
--- Siempre cerrar el cursor y liberar la memoria usada
CLOSE ROW_CURSOR
DEALLOCATE ROW_CURSOR -- Desreferencia el cursos en disco para cerrar su coneixi�n a disco.
/*
New CURSOR to validate if there are students en each SCHOOL
Same script as above but with conditionals.
*/
USE DB_JP_SQL_BASICO
DECLARE @S_NAME VARCHAR(255), @NUM_OF_STUDENTS INT
DECLARE ROW_CURSOR CURSOR LOCAL FAST_FORWARD FOR
(SELECT NAME, NUM_OF_STUDENTS FROM SCHOOL)
OPEN ROW_CURSOR
FETCH NEXT FROM ROW_CURSOR INTO @S_NAME, @NUM_OF_STUDENTS
WHILE @@FETCH_STATUS = 0
BEGIN
IF @NUM_OF_STUDENTS IS NOT NULL BEGIN
PRINT CONCAT('The school name is: ',@S_NAME,'. It has ', @NUM_OF_STUDENTS, ' students')
END
ELSE BEGIN
PRINT CONCAT('The school name is: ',@S_NAME,'. It has unknown number of students')
END
FETCH NEXT FROM ROW_CURSOR INTO @S_NAME, @NUM_OF_STUDENTS
END
CLOSE ROW_CURSOR
DEALLOCATE ROW_CURSOR