/
22_StoredProcedures_Demo.sql
356 lines (281 loc) · 7.31 KB
/
22_StoredProcedures_Demo.sql
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
/******************************************************************************
Course videos: https://www.red-gate.com/hub/university/courses/t-sql/tsql-for-beginners
Course scripts: https://litknd.github.io/TSQLBeginners
Stored Procedures
EXAMPLES FOR STUDY
*****************************************************************************/
/* ✋🏻 Doorstop ✋🏻 */
RAISERROR(N'Did you mean to run the whole thing?', 20, 1) WITH LOG;
GO
/******************************************************************************
Set up sample data
*****************************************************************************/
USE master;
GO
IF DB_ID('TSQLSchool') IS NOT NULL
BEGIN
ALTER DATABASE TSQLSchool SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE TSQLSchool
END
GO
CREATE DATABASE TSQLSchool;
GO
USE TSQLSchool;
GO
--DROP IF EXISTS is SQL Server 2016 SP3+
DROP TABLE IF EXISTS dbo.doggos,
dbo.jobbos,
dbo.doggoswithjobbos;
GO
CREATE TABLE dbo.doggos
(
dogid INT IDENTITY,
doggo VARCHAR(128) NOT NULL,
age TINYINT NOT NULL,
sex CHAR(1) NOT NULL,
CONSTRAINT pk_doggos
PRIMARY KEY CLUSTERED (dogid)
);
GO
CREATE TABLE dbo.jobbos
(
jobid INT IDENTITY,
jobbo VARCHAR(128) NOT NULL,
CONSTRAINT pk_jobbos
PRIMARY KEY CLUSTERED (jobid)
);
GO
CREATE TABLE dbo.doggoswithjobbos
(
dobbojobboid INT IDENTITY,
dogid INT NOT NULL,
jobid INT NOT NULL,
CONSTRAINT pk_doggoswithjobbos
PRIMARY KEY CLUSTERED (dobbojobboid),
INDEX uq_dogid_jobid (dogid, jobid)
);
GO
--And now, some foreign keys
ALTER TABLE dbo.doggoswithjobbos
ADD CONSTRAINT fk_doggoswithjobbos_dogid
FOREIGN KEY (dogid)
REFERENCES dbo.doggos (dogid);
GO
ALTER TABLE dbo.doggoswithjobbos
ADD CONSTRAINT fk_doggoswithjobbos_jobid
FOREIGN KEY (jobid)
REFERENCES dbo.jobbos (jobid);
GO
INSERT dbo.doggos
(
doggo,
age,
sex
)
VALUES
('Mister', 10, 'M'),
('Stormy', 3, 'M'),
('Wendell', 5, 'M'),
('Kota', 10, 'F'),
('Fletcher', 4, 'M'),
('Fletcher', 1, 'F'),
('Scout', 2, 'F');
GO
INSERT dbo.jobbos
(
jobbo
)
VALUES
('Tootstah'),
('Cuddler'),
('Patrollster'),
('Mushroom'),
('Best Fren'),
('Gymster');
GO
INSERT dbo.doggoswithjobbos
(
dogid,
jobid
)
VALUES
(1, 1),
(1, 3),
(1, 5),
(2, 2),
(2, 4),
(2, 5),
(3, 2),
(3, 3),
(3, 5),
(4, 2),
(4, 5),
(5, 2),
(5, 3),
(5, 5),
(6, 5),
(6, 6),
(7, 1);
GO
/******************************************************************************
Why use stored procedures?
* Batch multiple statements (including modifications)
* Return data in a variety of ways (datasets, output parameters)
* Parameterize and modularize code, make TSQL reusable
* Handle errors, return a status value
We are just going to scratch the surface
*****************************************************************************/
--CREATE OR ALTER starts with SQL Server 2016 SP1.
--Procedures can return a dataset
CREATE OR ALTER PROCEDURE dbo.doginfofordoggo @doggo VARCHAR(128)
AS
SELECT dogid,
sex,
age
FROM dbo.doggos
WHERE doggo = @doggo;
GO
--This uses 'position' to supply a value for the parameter
EXEC dbo.doginfofordoggo 'Wendell';
GO
--This explicitly names the parameter and assigns a value
EXEC dbo.doginfofordoggo @doggo = 'Mister';
GO
--This explicitly names the parameter and assigns a value
EXEC dbo.doginfofordoggo @doggo = 'Fletcher';
GO
/******************************************************************************
PARAMETERS - INPUT & OUTPUT
*****************************************************************************/
--Procedures can also return OUTPUT parameters
--This can be useful if we're looking to output single values
--This procedure has one input parameter and three output parameters
CREATE OR ALTER PROCEDURE dbo.doginfofordoggo
@doggo VARCHAR(128),
@dogid INT OUTPUT,
@sex CHAR(1) OUTPUT,
@age TINYINT OUTPUT
AS
SELECT @dogid = dogid,
@sex = sex,
@age = age
FROM dbo.doggos
WHERE doggo = @doggo;
GO
--Using the output parameters...
--Note: look at the data. What happened here? There is more than one Fletcher!
DECLARE @dogidOUTPUT INT,
@sexOUTPUT CHAR(1),
@ageOUTPUT TINYINT;
EXEC dbo.doginfofordoggo @doggo = 'Fletcher',
@dogid = @dogidOUTPUT OUT,
@sex = @sexOUTPUT OUT,
@age = @ageOUTPUT OUT;
SELECT @dogidOUTPUT as dogidOUTPUT,
@sexOUTPUT as sexOUTPUT,
@ageOUTPUT as ageOUTPUT;
GO
--Here is a procedure that gets scalar values from a sub-procedure via OUTPUT parameters
--It then uses those values in another query to return a dataset
CREATE OR ALTER PROCEDURE dbo.jobboandinfofordoggo @doggo VARCHAR(128)
AS
DECLARE @dogidOUTPUT INT,
@sexOUTPUT CHAR(1),
@ageOUTPUT TINYINT;
EXEC dbo.doginfofordoggo @doggo = @doggo,
@dogid = @dogidOUTPUT OUT,
@sex = @sexOUTPUT OUT,
@age = @ageOUTPUT OUT;
SELECT dogid,
@sexOUTPUT AS sex,
@ageOUTPUT AS age,
j.jobbo
FROM dbo.doggoswithjobbos AS dwj
JOIN dbo.jobbos AS j
ON dwj.jobid = j.jobid
WHERE dogid = @dogidOUTPUT;
GO
EXEC dbo.jobboandinfofordoggo @doggo = 'Scout';
GO
EXEC dbo.jobboandinfofordoggo @doggo = 'Stormy';
GO
/******************************************************************************
PASSING DATASETS BETWEEN PROCEDURES (one example)
*****************************************************************************/
--What if we want to use a dataset returned by a procedure in another procedure?
--This procedure returns a dataset
CREATE OR ALTER PROCEDURE dbo.doggosbyage @age TINYINT
AS
SELECT dogid,
doggo,
sex
FROM dbo.doggos
WHERE age = @age
GO
--It may return one row
EXEC dbo.doggosbyage @age = 2;
GO
--Or multiple rows
EXEC dbo.doggosbyage @age = 10;
GO
--This procedure calls dbo.doggosbyage, puts the data in a temporary table
--And then runs a query using that temporary table
CREATE OR ALTER PROCEDURE dbo.doginfoandjobsbyage @age TINYINT
AS
CREATE TABLE #doggos
(
dogid INT,
doggo VARCHAR(128) NOT NULL,
sex CHAR(1) NOT NULL
);
--INSERT ... EXEC puts the dataset from the procedure into a table
--In this case it's a temporary table
INSERT #doggos
(
dogid,
doggo,
sex
)
EXEC dbo.doggosbyage @age;
SELECT d.dogid,
d.doggo,
d.sex,
j.jobbo
FROM #doggos AS d
JOIN dbo.doggoswithjobbos AS dwj
ON d.dogid = dwj.dogid
JOIN dbo.jobbos AS j
ON j.jobid = dwj.jobid;
GO
EXEC dbo.doginfoandjobsbyage @age = 2;
GO
/******************************************************************************
IF BRANCHING - ONE EXAMPLE
*****************************************************************************/
CREATE OR ALTER PROCEDURE dbo.IfIfIf @doggo VARCHAR(128)
AS
IF @doggo IS NULL
BEGIN
SELECT 'All doggo branch' AS col1,
doggo
FROM dbo.doggos;
END
ELSE IF @doggo = 'Mister'
SELECT 'Mister branch' AS col1,
d.age,
j.jobbo
FROM dbo.doggos AS d
JOIN dbo.doggoswithjobbos AS dwj
ON d.dogid = dwj.dogid
JOIN dbo.jobbos AS j
ON dwj.jobid = j.jobid
WHERE d.doggo = @doggo;
ELSE
SELECT 'ELSE branch' AS col1;
GO
EXEC dbo.IfIfIf @doggo = NULL;
GO
EXEC dbo.IfIfIf @doggo = 'Mister';
GO
EXEC dbo.IfIfIf @doggo = 'Whatever';
GO