Skip to content

Commit 31ba9f9

Browse files
authored
Merge pull request microsoft#145 from JocaPC/master
JSON CRUD generator
2 parents c3ad03b + c470a54 commit 31ba9f9

File tree

3 files changed

+674
-1
lines changed

3 files changed

+674
-1
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
# T-SQL Procedures that generate T-SQL JSON CRUD procedures
2+
3+
This project contains a set of T-SQL scripts that generate:
4+
- Stored procedures that INSERT, UPDATE, or MERGE input JSON text into table
5+
- Stored procedures that generate SELECT statements that generate JSON from SQL tables.
6+
7+
### Contents
8+
9+
[About this sample](#about-this-sample)<br/>
10+
[Setup](#setup)<br/>
11+
[Generate](#generate)<br/>
12+
[Modify generated source](#modify)<br/>
13+
14+
<a name=about-this-sample></a>
15+
16+
## About this sample
17+
18+
- **Applies to:** SQL Server 2016 (or higher), Azure SQL Database
19+
- **Programming Language:** Transact-SQL
20+
- **Authors:** Jovan Popovic
21+
22+
<a name="setup"></a>
23+
24+
## Setup
25+
26+
To generate procedures, apply script in generate-json-crud.sql file.
27+
28+
<a name="generate"></a>
29+
## Generate procedures
30+
31+
32+
** GENERATE CRUD Functions for WWI tables. **
33+
34+
```sql
35+
declare @SchemaName sysname = 'Application' --> Name of the table where we want to insert JSON
36+
declare @TableName sysname = 'People' --> Name of the table schema where we want to insert JSON
37+
declare @JsonColumns nvarchar(max) = '|CustomFields|' --> List of pipe-separated NVARCHAR(MAX) column names that contain JSON text
38+
declare @IgnoredColumns nvarchar(max) = N'LastEditedBy' --> List of comma-separated columns that should not be imported
39+
40+
print (codegen.GenerateJsonCreateProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
41+
print (codegen.GenerateJsonRetrieveProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
42+
print (codegen.GenerateJsonUpdateProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
43+
print (codegen.GenerateJsonUpsertProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
44+
45+
GO
46+
47+
declare @SchemaName sysname = 'Sales' --> Name of the table where we want to insert JSON
48+
declare @TableName sysname = 'Orders' --> Name of the table schema where we want to insert JSON
49+
declare @JsonColumns nvarchar(max) = '||' --> List of pipe-separated NVARCHAR(MAX) column names that contain JSON text
50+
declare @IgnoredColumns nvarchar(max) = N'LastEditedBy,LastEditedWhen' --> List of comma-separated columns that should not be imported
51+
52+
53+
print (codegen.GenerateJsonCreateProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
54+
print (codegen.GenerateJsonRetrieveProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
55+
print (codegen.GenerateJsonUpdateProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
56+
print (codegen.GenerateJsonUpsertProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
57+
58+
GO
59+
60+
declare @SchemaName sysname = 'Application' --> Name of the table where we want to insert JSON
61+
declare @TableName sysname = 'Countries' --> Name of the table schema where we want to insert JSON
62+
declare @JsonColumns nvarchar(max) = '||' --> List of pipe-separated NVARCHAR(MAX) column names that contain JSON text, e.g. '|AdditionalContactInfo|Demographics|'
63+
declare @IgnoredColumns nvarchar(max) = N'LastEditedBy' --> List of comma-separated columns that should not be imported
64+
65+
66+
print (codegen.GenerateJsonCreateProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
67+
print (codegen.GenerateJsonRetrieveProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
68+
print (codegen.GenerateJsonUpdateProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
69+
print (codegen.GenerateJsonUpsertProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
70+
71+
GO
72+
73+
declare @SchemaName sysname = 'Application' --> Name of the table where we want to insert JSON
74+
declare @TableName sysname = 'Cities' --> Name of the table schema where we want to insert JSON
75+
declare @JsonColumns nvarchar(max) = '||' --> List of pipe-separated NVARCHAR(MAX) column names that contain JSON text, e.g. '|AdditionalContactInfo|Demographics|'
76+
declare @IgnoredColumns nvarchar(max) = N'Location,LastEditedBy' --> List of comma-separated columns that should not be imported
77+
78+
79+
print (codegen.GenerateJsonCreateProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
80+
print (codegen.GenerateJsonRetrieveProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
81+
print (codegen.GenerateJsonUpdateProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
82+
print (codegen.GenerateJsonUpsertProcedure('Website', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
83+
84+
85+
```
86+
87+
88+
**GENERATE CRUD Functions for Custom table.**
89+
90+
```sql
91+
DROP TABLE IF EXISTS dbo.Product
92+
GO
93+
CREATE TABLE dbo.Product(
94+
ProductID int IDENTITY PRIMARY KEY,
95+
Name nvarchar(50) NOT NULL,
96+
Color nvarchar(15) NULL,
97+
Size nvarchar(5) NULL,
98+
Price money NOT NULL,
99+
[Special JSON chars: " \ /
100+
] int NULL,
101+
[Special sql chars [[ " ]]
102+
] int NULL,
103+
Data nvarchar(4000) NULL,
104+
Tags nvarchar(4000) NULL,
105+
DateCreated datetime2 NOT NULL DEFAULT(GETDATE())
106+
)
107+
GO
108+
109+
declare @SchemaName sysname = 'dbo' --> Name of the table where we want to insert JSON
110+
declare @TableName sysname = 'Product' --> Name of the table schema where we want to insert JSON
111+
declare @JsonColumns nvarchar(max) = '|Data|Tags|' --> List of pipe-separated NVARCHAR(MAX) column names that contain JSON text, e.g. '|AdditionalContactInfo|Demographics|'
112+
declare @IgnoredColumns nvarchar(max) = N'DateCreated' --> List of comma-separated columns that should not be imported
113+
114+
print (codegen.GenerateJsonCreateProcedure('dbo', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
115+
116+
print (codegen.GenerateJsonRetrieveProcedure('dbo', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
117+
118+
print (codegen.GenerateJsonUpdateProcedure('dbo', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
119+
120+
print (codegen.GenerateJsonUpsertProcedure('dbo', @SchemaName, @TableName, @JsonColumns, @IgnoredColumns))
121+
122+
```
123+
124+
## Modify generated code
125+
126+
You can create your own functions codegen.GenerateProcedureHead and codegen.GenerateProcedureTail to generate custom header and footer for every generated procedure, e.g.:
127+
128+
```sql
129+
130+
DROP FUNCTION IF EXISTS codegen.GenerateProcedureHead
131+
GO
132+
CREATE FUNCTION codegen.GenerateProcedureHead(@Table sysname, @JsonParam sysname)
133+
RETURNS NVARCHAR(max)
134+
AS BEGIN
135+
136+
Declare @ret nvarchar(max) = '
137+
SET XACT_ABORT ON;
138+
139+
DECLARE @HelpMessage nvarchar(max) = N''JSON '+ @Table +' data is invalid.
140+
Execute SELECT TOP 1 * FROM ' + @Table + ' FOR JSON PATH to see an example of required JSON structure.'';
141+
142+
IF ISJSON('+ @JsonParam + ') = 0
143+
BEGIN
144+
PRINT @HelpMessage;
145+
THROW 51000, N'''+ @JsonParam + ' must be valid JSON data'', 1;
146+
RETURN 1;
147+
END;
148+
149+
BEGIN TRY
150+
151+
BEGIN TRAN;
152+
153+
';
154+
155+
RETURN @ret
156+
157+
END
158+
GO
159+
160+
GO
161+
DROP FUNCTION IF EXISTS codegen.GenerateProcedureTail
162+
GO
163+
CREATE FUNCTION codegen.GenerateProcedureTail(@Table sysname)
164+
RETURNS NVARCHAR(max)
165+
AS BEGIN
166+
167+
Declare @ret nvarchar(max) = '
168+
169+
IF @@ROWCOUNT = 0
170+
BEGIN
171+
PRINT N''Warning: No valid '+@Table+' data found'';
172+
PRINT @HelpMessage;
173+
END;
174+
175+
COMMIT;
176+
177+
END TRY
178+
BEGIN CATCH
179+
PRINT @HelpMessage;
180+
PRINT ERROR_MESSAGE();
181+
182+
THROW 51000, N''Valid JSON was supplied but does not match the '+@Table+' array structure'', 2;
183+
184+
IF XACT_STATE() <> 0 ROLLBACK TRAN;
185+
186+
RETURN 1;
187+
END CATCH;
188+
';
189+
190+
RETURN @ret
191+
192+
END
193+
GO
194+
```
195+
## Code of Conduct
196+
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.
197+
198+
## License
199+
These samples and templates are all licensed under the MIT license. See the license.txt file in the root.
200+
201+
## Questions
202+
Email questions to: [[email protected]](mailto: [email protected]).

0 commit comments

Comments
 (0)