Skip to content

Commit db4b4ab

Browse files
Merge pull request #116 from EmergentSoftware/dev
Using money data type check
2 parents 40f6c75 + f58b1aa commit db4b4ab

File tree

3 files changed

+75
-13
lines changed

3 files changed

+75
-13
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ The settings are located in the project "[\SQL-Server-Assess\Development Applica
171171

172172
# Current High Check Id
173173

174-
## Next Check Id: 28
174+
## Next Check Id: 29
175175

176176
# Naming Conventions
177177

@@ -486,7 +486,7 @@ Being frugal with memory is important for large tables, not only to save space b
486486

487487

488488
## Using MONEY Data Type
489-
**Check Id:** [NONE YET]
489+
**Check Id:** 28
490490

491491
The MONEY data type confuses the storage of data values with their display, though it clearly suggests, by its name, the sort of data held. Use DECIMAL(19, 4) instead. It is proprietary to SQL Server.
492492

Test Database/Tables/dbo.DataType.sql

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CREATE TABLE [dbo].[DataType]
2+
(
3+
[DataTypeId] [int] NOT NULL,
4+
[UnitPriceTotal] [money] NULL,
5+
[UnitPrice] [smallmoney] NULL,
6+
[ProductDescription] [text] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
7+
[ProductDescriptionInternational] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
8+
[LineAmount] [float] NULL,
9+
[LineTotal] [real] NULL,
10+
[ProfileInformation] [sql_variant] NULL
11+
) ON [PRIMARY]
12+
GO
13+
ALTER TABLE [dbo].[DataType] ADD CONSTRAINT [PK_DataType] PRIMARY KEY CLUSTERED ([DataTypeId]) ON [PRIMARY]
14+
GO

sp_Develop.sql

+59-11
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@
2626
** OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2727
** OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2828
**********************************************************************************************************************/
29-
CREATE OR ALTER PROCEDURE dbo.sp_Develop
29+
IF OBJECT_ID('dbo.sp_Develop') IS NULL
30+
BEGIN
31+
EXEC dbo.sp_executesql
32+
@stmt = N'CREATE PROCEDURE dbo.sp_Develop AS BEGIN SET NOCOUNT ON; END';
33+
END;
34+
GO
35+
36+
ALTER PROCEDURE dbo.sp_Develop
3037
@DatabaseName NVARCHAR(128) = NULL /*Defaults to current DB if not specified*/
3138
,@GetAllDatabases BIT = 0
3239
,@BringThePain BIT = 0
@@ -74,8 +81,8 @@ AS
7481
** Setting some varibles
7582
**********************************************************************************************************************/
7683

77-
SET @Version = '0.11.5';
78-
SET @VersionDate = '20200906';
84+
SET @Version = '0.11.6';
85+
SET @VersionDate = '20200909';
7986
SET @URLBase = 'https://github.com/EmergentSoftware/SQL-Server-Assess#';
8087
SET @OutputType = UPPER(@OutputType);
8188
SET @LineFeed = CHAR(13) + CHAR(10);
@@ -167,7 +174,7 @@ AS
167174
AND (@SkipCheckSchema IS NOT NULL AND RTRIM(LTRIM(@SkipCheckSchema)) <> '')
168175
AND (@SkipCheckDatabase IS NOT NULL AND RTRIM(LTRIM(@SkipCheckDatabase)) <> '')
169176
BEGIN
170-
177+
171178
IF @Debug IN (1, 2)
172179
RAISERROR('Inserting SkipChecks', 0, 1) WITH NOWAIT;
173180

@@ -1849,7 +1856,7 @@ AS
18491856
END;
18501857

18511858
CREATE TABLE #TableList (
1852-
TableSearchId INT NOT NULL IDENTITY(1, 1) PRIMARY KEY
1859+
TableListId INT NOT NULL IDENTITY(1, 1) PRIMARY KEY
18531860
,object_id INT NOT NULL
18541861
,schema_id INT NOT NULL
18551862
,SchemaName NVARCHAR(128) NOT NULL
@@ -1948,15 +1955,15 @@ AS
19481955
/* Loop through #TableList to figure out if the non-Always Encrypt columns have some sort of hashing or encryption */
19491956

19501957
DECLARE
1951-
@TableSearchId INT
1958+
@TableListId INT
19521959
,@SchemaName NVARCHAR(128)
19531960
,@TableName NVARCHAR(128)
19541961
,@ColumnName NVARCHAR(128);
19551962

19561963
WHILE EXISTS (SELECT * FROM #TableList WHERE IsProcessedFlag = 0 AND encryption_type = 0)
19571964
BEGIN
19581965
SELECT TOP (1)
1959-
@TableSearchId = TL.TableSearchId
1966+
@TableListId = TL.TableListId
19601967
,@SchemaName = TL.SchemaName
19611968
,@TableName = TL.TableName
19621969
,@ColumnName = TL.ColumnName
@@ -1965,7 +1972,7 @@ AS
19651972
WHERE
19661973
TL.IsProcessedFlag = 0
19671974
ORDER BY
1968-
TL.TableSearchId;
1975+
TL.TableListId;
19691976

19701977
SET @StringToExecute = N'
19711978
UPDATE
@@ -1984,7 +1991,7 @@ AS
19841991
' + QUOTENAME(@ColumnName) + N' IS NOT NULL
19851992
) AS T
19861993
WHERE
1987-
TL.TableSearchId = ' + CAST(@TableSearchId AS NVARCHAR(MAX)) + N';';
1994+
TL.TableListId = ' + CAST(@TableListId AS NVARCHAR(MAX)) + N';';
19881995

19891996
EXEC sys.sp_executesql @stmt = @StringToExecute;
19901997
IF @Debug = 2 AND @StringToExecute IS NOT NULL PRINT @StringToExecute;
@@ -1994,7 +2001,7 @@ AS
19942001
SET
19952002
IsProcessedFlag = 1
19962003
WHERE
1997-
TableSearchId = @TableSearchId;
2004+
TableListId = @TableListId;
19982005
END;
19992006

20002007
/* Find columns with potential unencrypted data */
@@ -2018,12 +2025,53 @@ AS
20182025
#TableList AS TL
20192026
WHERE
20202027
TL.encryption_type IS NULL
2021-
AND TL.MinimumColumnLength <= TL.StandardColumnLength * 1.3
2028+
AND TL.MinimumColumnLength <= TL.StandardColumnLength * 1.3 /* The "* 1.3" is allowing a 30% buffer above standard column length to look for encryption/hashing. */
20222029

20232030
DROP TABLE #TableList;
20242031

20252032
END;
20262033

2034+
/**********************************************************************************************************************/
2035+
SELECT
2036+
@CheckId = 28
2037+
,@Priority = 1
2038+
,@FindingGroup = 'Data Type Conventions'
2039+
,@Finding = 'Using MONEY data type'
2040+
,@URLAnchor = 'using-money-data-type';
2041+
/**********************************************************************************************************************/
2042+
IF NOT EXISTS (SELECT 1 FROM #SkipCheck AS SC WHERE SC.CheckId = @CheckId AND SC.ObjectName IS NULL)
2043+
BEGIN
2044+
IF @Debug IN (1, 2) RAISERROR(N'Running CheckId [%d]', 0, 1, @CheckId) WITH NOWAIT;
2045+
2046+
SET @StringToExecute = N'
2047+
INSERT INTO
2048+
#Finding (CheckId, Database_Id, DatabaseName, FindingGroup, Finding, URL, Priority, Schema_Id, SchemaName, Object_Id, ObjectName, ObjectType, Details)
2049+
SELECT
2050+
CheckId = ' + CAST(@CheckId AS NVARCHAR(MAX)) + N'
2051+
,Database_Id = ' + CAST(@DatabaseId AS NVARCHAR(MAX)) + N'
2052+
,DatabaseName = ''' + CAST(@DatabaseName AS NVARCHAR(MAX)) + N'''
2053+
,FindingGroup = ''' + CAST(@FindingGroup AS NVARCHAR(MAX)) + N'''
2054+
,Finding = ''' + CAST(@Finding AS NVARCHAR(MAX)) + N'''
2055+
,URL = ''' + CAST(@URLBase + @URLAnchor AS NVARCHAR(MAX)) + N'''
2056+
,Priority = ' + CAST(@Priority AS NVARCHAR(MAX)) + N'
2057+
,Schema_Id = S.schema_id
2058+
,SchemaName = S.name
2059+
,Object_Id = O.object_id
2060+
,ObjectName = O.name + ''.'' + C.Name
2061+
,ObjectType = ''COLUMN''
2062+
,Details = N''This column uses the '' + UPPER(T.name) + N'' data type, which has limited precision and can lead to roundoff errors. Consider using DECIMAL(19, 4) instead.''
2063+
FROM
2064+
' + QUOTENAME(@DatabaseName) + N'.sys.objects AS O
2065+
INNER JOIN ' + QUOTENAME(@DatabaseName) + N'.sys.schemas AS S ON S.schema_id = O.schema_id
2066+
INNER JOIN ' + QUOTENAME(@DatabaseName) + N'.sys.columns AS C ON C.object_id = O.object_id
2067+
INNER JOIN ' + QUOTENAME(@DatabaseName) + N'.sys.types AS T on T.user_type_id = C.user_type_id
2068+
WHERE
2069+
T.name IN (''money'', ''smallmoney'');';
2070+
2071+
EXEC sys.sp_executesql @stmt = @StringToExecute;
2072+
IF @Debug = 2 AND @StringToExecute IS NOT NULL PRINT @StringToExecute;
2073+
END;
2074+
20272075

20282076
-- SQL Prompt formatting on
20292077
/**********************************************************************************************************************

0 commit comments

Comments
 (0)