What's the Recommended Location for SQL (Ddl) Scripts

What's the recommended location for SQL (DDL) scripts?

I think there is no best practice for this. In my past project, I created a separate directory for storing such SQL script.

For example src/main/db.

It won't be packaged to final JAR by default (which are the preferred way in most case), yet it is convenient enough to let it packaged in assembly. You can even package them in the main artifact JAR, by adding corresponding resource declaration or using maven build-helper plugin.

However, all depends on your usage on this script. My simple "rule of thumb" is that, I would consider putting them in resources/ only when they are really resources to be loaded by the application.

How to store/organize DDL script?

We have following folder structure

+ddl
....group1_ddl.sql
....group2_ddl.sql
+procedures
---level1
......single_sp.sql
......another_sp.sql
---level2
......another_uses_level1_sp.sql
---leveln
......remaining_sp.sql
+views
--level1
......group_of_views.sql

As you can see we have 3 top level folders, each for ddl, sps and views

DDL

90% of time we have one ddl script for all the tables
Some times we mainitain ddl scripts separately which can be separated logically
ex: staging_ddl.sql, aggrigate_ddl.sql
ddl script includes PK and FK constriants and also additional indeces

Stored Procedures

  1. Note the multiple folders (level1, level2), since our our entire ETL
    & business is implemented in stored procedures so we have lot of sps
    (dozens) with hundreds of lines of code. Since we are wrote modular
    coding we have some sps depending on other sps. So the sps which
    depend on other sps go to higher level

    ex: In our scenario main_sp.sql is one sp which runs the entire workflow, this sp intern calls rest of the sps in the sequential order and they intern may or may not call other sps

  2. so main_sp.sql goes to the level3, child_sp.sql goes to level2,
    grand_child_sp.sql goes to level1

  3. file name is same as sp name

Views:

  1. If your views are less complex and you think you can maintain easily
    you can manage them in a single script.
  2. But in our case they are some views with nearly over 2000 lines so
    we maintained them in one script per view.
  3. Mostly we try to avoid using a view in another view, in case we did
    it then we maintain the multiple level hierachy as explained above
    otherwise we maintain single script per view
  4. file name is same as view name

This is how I have been managing the scripts successfully since over 7 years.

Hope this helps

Where should I put the SQL files in my Java project?

In a Java/Maven setting we use as project hierarchy:

project/src/main/java/Package/Class.java
project/src/test/java/Package/ClassTest.java
project/src/main/resources/Package/resource.properties
project/src/test/resources/Package/test_resource.properties

And in order to answer your question: I would put the SQL-files along with the resources under src/main/resources.

You may want to have a look at this thread.

generate DDL script from SQL Server database

For tables : (you can work as follows)

DECLARE @C VARCHAR(200)
DECLARE C CURSOR FOR
SELECT 'EXEC [DBO].[SP_GETDDL] '''+NAME+'''' FROM SYS.TABLES
OPEN C
FETCH NEXT FROM C INTO @C
WHILE @@FETCH_STATUS=0
BEGIN
EXEC (@C)
FETCH NEXT FROM C INTO @C
END
CLOSE C
DEALLOCATE C

The Procedure is as follows:

CREATE PROCEDURE [dbo].[Sp_getddl] @TBL VARCHAR(255) 
AS
BEGIN
SET nocount ON

DECLARE @TBLNAME VARCHAR(200),
@SCHEMANAME VARCHAR(255),
@STRINGLEN INT,
@TABLE_ID INT,
@FINALSQL VARCHAR(max),
@CONSTRAINTSQLS VARCHAR(max),
@CHECKCONSTSQLS VARCHAR(max),
@RULESCONSTSQLS VARCHAR(max),
@FKSQLS VARCHAR(max),
@TRIGGERSTATEMENT VARCHAR(max),
@EXTENDEDPROPERTIES VARCHAR(max),
@INDEXSQLS VARCHAR(max),
@vbCrLf CHAR(2)

SET @vbCrLf = Char(13) + Char(10)

SELECT @SCHEMANAME = Isnull(Parsename(@TBL, 2), 'dbo'),
@TBLNAME = Parsename(@TBL, 1)

SELECT @TABLE_ID = [object_id]
FROM sys.objects
WHERE [type] = 'U'
AND [name] <> 'dtproperties'
AND [name] = @TBLNAME
AND [schema_id] = Schema_id(@SCHEMANAME);

IF Isnull(@TABLE_ID, 0) = 0
BEGIN
SET @FINALSQL = 'Table object [' + @SCHEMANAME + '].['
+ Upper(@TBLNAME)
+ '] does not exist in Database ['
+ Db_name() + ']'

SELECT @FINALSQL;

RETURN 0
END

SELECT @FINALSQL = 'CREATE TABLE [' + @SCHEMANAME + '].['
+ Upper(@TBLNAME) + '] ( '

SELECT @TABLE_ID = Object_id(@TBLNAME)

SELECT @STRINGLEN = Max(Len(sys.columns.[name])) + 1
FROM sys.objects
INNER JOIN sys.columns
ON sys.objects.[object_id] = sys.columns.[object_id]
AND sys.objects.[object_id] = @TABLE_ID;

SELECT @FINALSQL = @FINALSQL + CASE WHEN sys.columns.[is_computed] = 1
THEN
@vbCrLf +
'[' + Upper(
sys.columns.[name]) + '] ' + Space(@STRINGLEN -
Len(sys.columns.[name])) + 'AS ' +
Isnull(CALC.definition, '') ELSE
@vbCrLf + '[' + Upper(sys.columns.[name]) + '] '
+
Space(
@STRINGLEN - Len(sys.columns.[name])) +
Upper(Type_name(sys.columns.[user_type_id])) +
CASE
WHEN
Type_name(sys.columns.[user_type_id]) IN (
'decimal',
'numeric') THEN '(' + CONVERT(
VARCHAR, sys.columns.[precision]) + ',' +
CONVERT(
VARCHAR,
sys.columns.[scale]) + ') ' + Space(6 - Len(
CONVERT(
VARCHAR,
sys.columns.[precision]) + ',' +
CONVERT(VARCHAR, sys.columns.[scale]))) + Space(
2)
-- + SPACE(16 - LEN(TYPE_NAME(sys.columns.[user_type_id])))
+ CASE WHEN Columnproperty ( @TABLE_ID,
sys.columns.[name],
'IsIdentity' ) = 0 THEN ' ' ELSE
' IDENTITY(' +
CONVERT(VARCHAR, Isnull(Ident_seed(@TBLNAME), 1)
)
+
',' +
CONVERT(VARCHAR, Isnull(Ident_incr(@TBLNAME), 1)
)
+
')' END
+ CASE WHEN sys.columns.[is_nullable] = 0 THEN
' NOT NULL'
ELSE ' NULL' END WHEN
Type_name(sys.columns.[user_type_id]) IN (
'float',
'real')
THEN CASE WHEN
sys.columns.[precision] = 53 THEN Space(11 -
Len(CONVERT(VARCHAR, sys.columns.[precision])))
+
Space(7) +
Space(16 -
Len(Type_name(sys.columns.[user_type_id]))) +
CASE
WHEN
sys.columns.[is_nullable] = 0 THEN
' NOT NULL' ELSE ' NULL' END ELSE '(' +
CONVERT(
VARCHAR,
sys.columns.[precision]) + ') ' + Space(6 - Len(
CONVERT(
VARCHAR, sys.columns.[precision]))) + Space(7) +
Space
(16
- Len(Type_name(sys.columns.[user_type_id]))) +
CASE
WHEN
sys.columns.[is_nullable] = 0 THEN ' NOT NULL'
ELSE
' NULL' END
END WHEN Type_name(sys.columns.[user_type_id])
IN
(
'char',
'varchar') THEN CASE WHEN
sys.columns.[max_length]
=
-1 THEN
'(max)' + Space(6 -
Len(CONVERT(VARCHAR, sys.columns.[max_length])))
+
Space(7) +
Space(16 -
Len(Type_name(sys.columns.[user_type_id]))) +
CASE
WHEN
sys.columns.collation_name IS NULL THEN ''
ELSE ' COLLATE ' + sys.columns.collation_name
END
+
CASE WHEN
sys.columns.[is_nullable] = 0 THEN ' NOT NULL'
ELSE
' NULL' END ELSE '(' +
CONVERT(VARCHAR, sys.columns.[max_length]) +
') '
+
Space(6 -
Len(CONVERT(VARCHAR, sys.columns.[max_length])))
+
Space(7) +
Space(16 -
Len(Type_name(sys.columns.[user_type_id]))) +
CASE
WHEN
sys.columns.collation_name IS NULL THEN ''
ELSE ' COLLATE ' + sys.columns.collation_name
END
+
CASE WHEN
sys.columns.[is_nullable] = 0 THEN ' NOT NULL'
ELSE
' NULL' END END WHEN
Type_name(sys.columns.[user_type_id]) IN (
'nchar',
'nvarchar'
) THEN CASE WHEN
sys.columns.[max_length] = -1 THEN '(max)' +
Space
(6 -
Len(CONVERT(VARCHAR, (sys.columns.[max_length]))))
+
Space(7)
+ Space(16 - Len(Type_name(
sys.columns.[user_type_id]))) + CASE WHEN
sys.columns.collation_name IS NULL THEN '' ELSE
' COLLATE ' +
sys.columns.collation_name END + CASE WHEN
sys.columns.[is_nullable] = 0 THEN
' NOT NULL' ELSE ' NULL' END ELSE '(' +
CONVERT(
VARCHAR,
(sys.columns.[max_length])) + ') ' + Space(6 - Len
(
CONVERT(
VARCHAR, (sys.columns.[max_length])))) + Space(7)
+
Space(16
- Len(Type_name(sys.columns.[user_type_id]))) +
CASE
WHEN
sys.columns.collation_name IS NOT NULL THEN ''
ELSE
' COLLATE ' +
sys.columns.collation_name END + CASE WHEN
sys.columns.[is_nullable]
= 0 THEN ' NOT NULL' ELSE ' NULL' END END WHEN
Type_name(
sys.columns.[user_type_id]) IN ('datetime',
'money',
'text',
'image') THEN Space(18 -
Len(Type_name(sys.columns.[user_type_id]))) +
' ' + CASE WHEN
sys.columns.[is_nullable] = 0 THEN ' NOT NULL'
ELSE
' NULL' END ELSE Space(16
- Len(Type_name(sys.columns.[user_type_id]))) +
CASE
WHEN
Columnproperty ( @TABLE_ID, sys.columns.[name],
'IsIdentity'
) = 0 THEN ' ' ELSE ' IDENTITY(' +
CONVERT(
VARCHAR, Isnull(Ident_seed(@TBLNAME), 1) ) + ',' +
CONVERT(
VARCHAR, Isnull(Ident_incr(@TBLNAME), 1) ) + ')'
END +
Space(
2) + CASE WHEN sys.columns.[is_nullable] = 0 THEN
' NOT NULL'
ELSE ' NULL' END END + CASE WHEN
sys.columns.[default_object_id] = 0 THEN ''
--ELSE ' DEFAULT ' + ISNULL(def.[definition] ,'')
--optional section in case NAMED default cosntraints are needed:
ELSE @vbCrLf + 'CONSTRAINT [' + def.NAME + '] DEFAULT ' +
Isnull(def.[definition], '')
--i thought it needed to be handled differently! NOT!
END --CASE cdefault
END --iscomputed
+ ','
FROM sys.columns
LEFT OUTER JOIN sys.default_constraints DEF
ON sys.columns.[default_object_id] = DEF.[object_id]
LEFT OUTER JOIN sys.computed_columns CALC
ON sys.columns.[object_id] = CALC.[object_id]
AND sys.columns.[column_id] = CALC.[column_id]
WHERE sys.columns.[object_id] = @TABLE_ID
ORDER BY sys.columns.[column_id]

SELECT @STRINGLEN = Max(Len([name])) + 1
FROM sys.objects

DECLARE @Results TABLE
(
[schema_id] INT,
[schema_name] VARCHAR(255),
[object_id] INT,
[object_name] VARCHAR(255),
[index_id] INT,
[index_name] VARCHAR(255),
[rows] INT,
[sizemb] DECIMAL(19, 3),
[indexdepth] INT,
[type] INT,
[type_desc] VARCHAR(30),
[fill_factor] INT,
[is_unique] INT,
[is_primary_key] INT,
[is_unique_constraint] INT,
[index_columns_key] VARCHAR(max),
[index_columns_include] VARCHAR(max)
)

INSERT INTO @Results
SELECT sys.schemas.schema_id,
sys.schemas.[name]
AS schema_name,
sys.objects.[object_id],
sys.objects.[name]
AS object_name,
sys.indexes.index_id,
Isnull(sys.indexes.[name], '---')
AS index_name,
partitions.rows,
partitions.sizemb,
Indexproperty(sys.objects.[object_id], sys.indexes.[name],
'IndexDepth')
AS
IndexDepth,
sys.indexes.type,
sys.indexes.type_desc,
sys.indexes.fill_factor,
sys.indexes.is_unique,
sys.indexes.is_primary_key,
sys.indexes.is_unique_constraint,
Isnull(Index_Columns.index_columns_key, '---')
AS index_columns_key,
Isnull(Index_Columns.index_columns_include, '---')
AS index_columns_include
FROM sys.objects
JOIN sys.schemas
ON sys.objects.schema_id = sys.schemas.schema_id
JOIN sys.indexes
ON sys.objects.[object_id] = sys.indexes.[object_id]
JOIN (SELECT [object_id],
index_id,
Sum(row_count) AS
Rows,
CONVERT(NUMERIC(19, 3), CONVERT(NUMERIC(19, 3), Sum(
in_row_reserved_page_count
+ lob_reserved_page_count
+
row_overflow_reserved_page_count
)) /
CONVERT(NUMERIC(19, 3), 128)) AS
SizeMB
FROM sys.dm_db_partition_stats
GROUP BY [object_id],
index_id) AS partitions
ON sys.indexes.[object_id] = partitions.[object_id]
AND sys.indexes.index_id = partitions.index_id
CROSS apply (SELECT LEFT(index_columns_key,
Len(index_columns_key) - 1)
AS
index_columns_key
,
LEFT(index_columns_include, Len(index_columns_include) - 1) AS
index_columns_include
FROM (SELECT (SELECT sys.columns.[name] + ',' + ' '
FROM sys.index_columns
JOIN sys.columns
ON sys.index_columns.column_id = sys.columns.column_id
AND sys.index_columns.[object_id] =
sys.columns.[object_id]
WHERE sys.index_columns.is_included_column = 0
AND sys.indexes.[object_id] =
sys.index_columns.[object_id]
AND sys.indexes.index_id = sys.index_columns.index_id
ORDER BY key_ordinal
FOR xml path('')) AS index_columns_key,
(SELECT sys.columns.[name] + ',' + ' '
FROM sys.index_columns
JOIN sys.columns
ON sys.index_columns.column_id = sys.columns.column_id
AND sys.index_columns.[object_id] =
sys.columns.[object_id]
WHERE sys.index_columns.is_included_column = 1
AND sys.indexes.[object_id] =
sys.index_columns.[object_id]
AND sys.indexes.index_id = sys.index_columns.index_id
ORDER BY index_column_id
FOR xml path('')) AS index_columns_include) AS Index_Columns) AS
Index_Columns
WHERE sys.schemas.[name] LIKE CASE
WHEN @SCHEMANAME = '' THEN
sys.schemas.[name]
ELSE @SCHEMANAME
END
AND sys.objects.[name] LIKE CASE
WHEN @TBLNAME = '' THEN
sys.objects.[name]
ELSE @TBLNAME
END
ORDER BY sys.schemas.[name],
sys.objects.[name],
sys.indexes.[name]

--@Results table has both PK,s Uniques and indexes in thme...pull them out for adding to funal results:
SET @CONSTRAINTSQLS = ''
SET @INDEXSQLS = ''

SELECT @CONSTRAINTSQLS = @CONSTRAINTSQLS + CASE WHEN is_primary_key = 1 OR
is_unique =
1 THEN @vbCrLf +
'CONSTRAINT [' + index_name + '] ' + Space
(
@STRINGLEN
- Len(index_name)) + CASE WHEN
is_primary_key =
1 THEN
' PRIMARY KEY ' ELSE CASE WHEN is_unique = 1
THEN
' UNIQUE ' ELSE '' END END + type_desc
+
CASE WHEN
type_desc='NONCLUSTERED' THEN '' ELSE ' '
END
+ ' ('
+ index_columns_key + ')' + CASE WHEN
index_columns_include <> '---' THEN
' INCLUDE ('
+
index_columns_include + ')' ELSE '' END +
CASE
WHEN
fill_factor <> 0 THEN ' WITH FILLFACTOR = '
+
CONVERT(
VARCHAR(30), fill_factor) ELSE '' END ELSE
''
END + ','
FROM @RESULTS
WHERE [type_desc] != 'HEAP'
AND is_primary_key = 1
OR is_unique = 1
ORDER BY is_primary_key DESC,
is_unique DESC

SELECT @INDEXSQLS = @INDEXSQLS + CASE WHEN is_primary_key = 0 OR is_unique =
0 THEN
@vbCrLf +
'CREATE INDEX [' + index_name + '] ' + Space(
@STRINGLEN
- Len(index_name)) + ' ON [' + [object_name] +
']' +
' (' +
index_columns_key + ')' + CASE WHEN
index_columns_include <>
'---' THEN ' INCLUDE (' + index_columns_include +
')'
ELSE
'' END + CASE WHEN fill_factor <> 0 THEN
' WITH FILLFACTOR = ' + CONVERT(VARCHAR(30),
fill_factor)
ELSE '' END END
FROM @RESULTS
WHERE [type_desc] != 'HEAP'
AND is_primary_key = 0
AND is_unique = 0
ORDER BY is_primary_key DESC,
is_unique DESC

IF @INDEXSQLS <> ''
SET @INDEXSQLS = @vbCrLf + 'GO' + @vbCrLf + @INDEXSQLS

SET @CHECKCONSTSQLS = ''

SELECT @CHECKCONSTSQLS = @CHECKCONSTSQLS + @vbCrLf
+ Isnull('CONSTRAINT [' + sys.objects.[name] +
'] ' +
Space(
@STRINGLEN - Len(sys.objects.[name])) +
' CHECK ' +
Isnull(sys.check_constraints.definition, '')
+
',', '')
FROM sys.objects
INNER JOIN sys.check_constraints
ON sys.objects.[object_id] =
sys.check_constraints.[object_id]
WHERE sys.objects.type = 'C'
AND sys.objects.parent_object_id = @TABLE_ID

SET @FKSQLS = '';

SELECT @FKSQLS = @FKSQLS + @vbCrLf + 'CONSTRAINT ['
+ Object_name(constid) + ']'
+ Space(@STRINGLEN - Len(Object_name(constid) ))
+ ' FOREIGN KEY (' + Col_name(fkeyid, fkey)
+ ') REFERENCES ' + Object_name(rkeyid) + '('
+ Col_name(rkeyid, rkey) + '),'
FROM sysforeignkeys
WHERE fkeyid = @TABLE_ID

SET @RULESCONSTSQLS = ''

SELECT @RULESCONSTSQLS = @RULESCONSTSQLS
+ Isnull( @vbCrLf +
'if not exists(SELECT [name] FROM sys.objects WHERE TYPE=''R'' AND schema_id = '
+ CONVERT(VARCHAR(30), sys.objects.schema_id) +
' AND [name] = ''[' +
Object_name(sys.columns.[rule_object_id]) + ']'')' +
@vbCrLf +
sys.sql_modules.definition + @vbCrLf + 'GO' + @vbCrLf +
'EXEC sp_binderule ['
+ sys.objects.[name] + '], ''[' +
Object_name(sys.columns.[object_id]) + '].[' +
sys.columns.[name] +
']''' + @vbCrLf + 'GO', '')
FROM sys.columns
INNER JOIN sys.objects
ON sys.objects.[object_id] = sys.columns.[object_id]
INNER JOIN sys.sql_modules
ON sys.columns.[rule_object_id] = sys.sql_modules.[object_id]
WHERE sys.columns.[rule_object_id] <> 0
AND sys.columns.[object_id] = @TABLE_ID

SET @TRIGGERSTATEMENT = ''

SELECT @TRIGGERSTATEMENT = @TRIGGERSTATEMENT + @vbCrLf
+ sys.sql_modules.[definition] + @vbCrLf + 'GO'
FROM sys.sql_modules
WHERE [object_id] IN(SELECT [object_id]
FROM sys.objects
WHERE type = 'TR'
AND [parent_object_id] = @TABLE_ID)

IF @TRIGGERSTATEMENT <> ''
SET @TRIGGERSTATEMENT = @vbCrLf + 'GO' + @vbCrLf + @TRIGGERSTATEMENT

SET @EXTENDEDPROPERTIES = ''

SELECT @EXTENDEDPROPERTIES = @EXTENDEDPROPERTIES + @vbCrLf
+ 'EXEC sys.sp_addextendedproperty @name = N''' + [name]
+ ''', @value = N'''
+ Replace(CONVERT(VARCHAR(max), [value]), '''',
'''''')
+
''', @level0type = N''SCHEMA'', @level0name = ['
+ @SCHEMANAME
+
'], @level1type = N''TABLE'', @level1name = ['
+ @TBLNAME + '];'
FROM Fn_listextendedproperty (NULL, 'schema', @SCHEMANAME, 'table',
@TBLNAME, NULL,
NULL);

IF @EXTENDEDPROPERTIES <> ''
SET @EXTENDEDPROPERTIES = @vbCrLf + 'GO' + @vbCrLf + @EXTENDEDPROPERTIES

SELECT @FINALSQL = @FINALSQL + @CONSTRAINTSQLS + @CHECKCONSTSQLS
+ @FKSQLS

SET @FINALSQL = Substring(@FINALSQL, 1, Len(@FINALSQL) - 1);
SET @FINALSQL = @FINALSQL + ')' + @vbCrLf;

SELECT @FINALSQL + @INDEXSQLS + @RULESCONSTSQLS
+ @TRIGGERSTATEMENT + @EXTENDEDPROPERTIES
END

go

Run all SQL files in a directory

Create a .BAT file with the following command:

for %%G in (*.sql) do sqlcmd /S servername /d databaseName -E -i"%%G"
pause

If you need to provide username and passsword

for %%G in (*.sql) do sqlcmd /S servername /d databaseName -U username -P 
password -i"%%G"

Note that the "-E" is not needed when user/password is provided

Place this .BAT file in the directory from which you want the .SQL files to be executed, double click the .BAT file and you are done!

SSMS - get DDL of all views in a schema

If you want to get the view definitions from a query, you can use sql_modules.

select   m.definition
from sys.sql_modules m
join sys.objects o on o.object_id = m.object_id
join sys.schemas s on s.schema_id = o.schema_id
where o.type = 'V'
and s.name in ('your', 'schemas', 'here')

Customize as desired to select the views you want.



Related Topics



Leave a reply



Submit