Register
Submit a solution
The challenge is finished.

Challenge Overview

Challenge Summary

Welcome to “Compilation of SQL Server Properties Challenge”. Our client would like to compile all possible SQL Server properties of all of their product installations in one place for further analysis and possible standardization of some of the configurations.

This challenge is to develop a T-SQL script that can be run on servers hosting databases of our client’s product. When run, the script should compile all available properties of the server, database & session. Output of script is a compilation of all properties of of ther server and database on which it is run, produced in a very easy to consume format. For complete definition of format of the output from this script, “Guidelines for producing Output Script”.

Our client seeks community members’ expertise and creative thinking in meeting their needs.

Full Description & Project Guide

Some facts about client’s product installation

  • Product installations are spread over 100s of servers ranging from SQL Server 2005 to 2014 versions
    An SQL Server instance may have multiple product databases
    We need to gather property values from the database on which the script is run. If the database is not a product database, an error should be raised (for how to identify if a db is product database see Table Definition Note 1)

Project Requirements & Restrictions

  • Client will handle the process of actual running of the script on as many databases as needed. In other words, scope of the script is current database on which it is run.
    Output of the script should list all properties described in Table 1 and their configured values (see guidelines for writing “Submission Script” and “Output Script”)
    If you can think of other config settings that may be of use, you are welcome to extend SystemSettings table and include such config settings in the Submission Script. Please clearly mark any such addition using comments.


Final Submission Guidelines

Guidelines for writing Submission Script

  • The script you will be submitting for the challenge will be referred to as “Submission Script”
    As a result of running Submission Script, an INSERT statement should be generated, targeting the table definition given below; where columns are from the target table below and values are property values read from server, db & session properties (The INSERT statement script generated by Submission Script will be referred to as “Output Script”; see Guidelines for producing Output Script for more details)
    Submission Script will be delivered in a single SQL source file named “gather_sql_environment.sql”. The file shall contain only the script block; the dbo.SystemSettings table will be created by separate means.
    Submission Script file format should be an 8-bit ASCII that uses a CarriageReturn/LineFeed pair as a line terminator.
    Running Submission Script should not make permanent changes to the schema or data (except manipulating export_bcp table; see Table Definition export_bcp for details). Usage of temporary tables (table variables preferred) and temporary stored procs is acceptable.
    Terminate all statements with a semi-colon.
    Comment code blocks liberally.
    Use code indentation for multi-line statements. Use spaces to indent, not tabs. Tab stops are every 2 characters.
    Target a max of 150 characters per line for code and comments. Beyond column 135 you should strongly consider wrapping the line.
    Capitalize all keywords.
    Use meaningful variable names. The first 3 characters are lowercase and indicate the datatype of the variable. The rest of the characters are CamelCase without underscores. Examples: @chvSomeVar, @intSomeNumber

Data Type

Prefix

Example

 

Binary

bny

@bnyControlNum

 

Bit

bit

@bitErr

 

Char

chr

@chrParmCode

 

Datetime

dtm

@dtmNow

 

Decimal

dec

@decHours2

 

Float

flt

@fltMinutes

 

Int

int

@intEmployeeId

 

Money

mny

@mnyAmount

 

Numeric

num

@numBatchEarnings014

 

Nvarchar

ncv

@ncvSqlErrMessage

 

Real

rel

@relHourlyAmount

 

Smalldatetime

dts

@dtsStartDate

 

Smallint

ins

@insLength

 

Smallmoney

mns

@mnsDollars

 

Table

tbl

@tblOutputCache

 

Tinyint

iny

@inyBCPOutputFlag

 

Uniqueidentifier

uig

@uigHandle

 

Varbinary

bnv

@bnvSafeNum  

 

Varchar

chv

@chvRedirSymbol

 

  • Commas follow column names, etc. Commas should not start a code line.
    Set-based logic is preferred over loops for processing. Do not use cursors.
    Code labels and GOTO statements should not be used.
    Always use COLLATE DATABASE_DEFAULT for string fields in any declared table variables or temp tables. NULL or NOT NULL should always be specified.
    TRY/CATCH blocks should be used for error handling. Precede every “BEGIN TRY” statement with a “SET NOCOUNT ON;” statement. This works around a compiler bug on certain versions of SQL 2012.

Guidelines for producing Output Script

  • The INSERT statement script generated by Submission Script will be referred to as “Output Script”
    Output Script should be a syntactically and semantically valid INSERT statement targeting CompanySqlEnvironment.dbo.SystemSettings table. See Table Definition SystemSettings for details.
    Generation of Output Script should use “xp_cmdshell bcp queryout” command
    Table dbo.export_bcp should be used as source for “bcp queryout”. See Table Definition export_bcp for details.
    export_bcp.session_guid is a newid() where ‘-‘s are removed
    Notice that export_bcp.data is limited to 8000 characters whereas xmls generated for columns dbo.System_Settings.TE_ColumnAnsiPadding, dbo.System_Settings.TE_ColumnCollations, dbo.System_Settings.TE_Sproc_Settings dbo.System_Settings.TE_TablesWithDroppedColumns, and dbo.System_Settings.TE_ProductHistory are well over this limit. Values for these columns should be broken down without loss of information

 

Allowed Technology

  • T-SQL compatible with SQL Server 2005 (compatibility level 90)

Table Definition SystemSettings

dbo.SystemSettings.sql defines the table that output script should target with an INSERT statement. A separate SQL file will be included containing this code for your convenience.

Table Definition Note 1

The following query demonstrates an acceptable method of determining whether a SQL database is a Product database:

  -- If any of the 9 tables in the query below don't exist in the database, it's not a Product database

  WITH

    CountOfProductTables

      (TableCount)

      AS

      (

        SELECT COUNT(1) AS TableCount

          FROM sys.tables

          WHERE name IN (

                          'audit_log', 'company', 'employee',

                          'navigation_tree', 'product_history',

                          'ref_parameter_type', 'security_user',

                          'session', 'template_master'

                        )

      )

  SELECT

      CASE TableCount WHEN 9 THEN 1 ELSE 0 END AS Is_Product_DB

    FROM CountOfProductTables;

 

Table Definition Note 2

This should be built from the name column in Product’s company table. If the database is not a Product DB, NULL should be returned. Note that company_id = 0 should be ignored and not returned here. The XML should be formatted with a root called “companies” and 1-n elements called “company” containing the names. An example is shown below:

 

  <companies>

    <company>ACME</company>

    <company>ACE</company>

  </companies>

 

For the purpose of this query, assume company table having columns company_id and name

 

Table Definition Note 3

The following query will return the version of a Product database. If the database is not Product, this query will fail.

 

  SELECT parameter_string as ProductReportedVersion

    FROM dbo.ref_parameter_type

    WHERE parameter_type = 'RV';

 

For the purpose of this query, assume ref_parameter_type table having columns parameter_string and parameter_type.

 

Table Definition Note 4

This will be an XML-formatted list of the ansi padding settings stored with database string columns. It will be generated using logic similar to the query shown below.

 

SELECT

    O.name            AS TableName    ,

    C.name            AS ColumnName   ,

    T.name            AS DataType     ,

    C.is_ansi_padded  AS IsAnsiPadded

  FROM    sys.columns AS C

    JOIN  sys.objects AS O  ON C.object_id = O.object_id

    JOIN  sys.types   AS T  ON    C.system_type_id = T.system_type_id

                              AND T.is_user_defined = 0

  WHERE O.type = 'U'

    AND C.collation_name IS NOT NULL

  ORDER BY O.name, C.column_id

  FOR XML PATH ('Column'), ROOT ('Columns');

 

An example of the format of the XML is below. There will be 1-n Column elements, one for each column returned by the query above:

 

  <Columns>

    <Column>

      <TableName>abra_hours_worked</TableName>

      <ColumnName>code</ColumnName>

      <DataType>varchar</DataType>

      <IsAnsiPadded>1</IsAnsiPadded>

    </Column>

    <Column>

      <TableName>abra_hours_worked</TableName>

      <ColumnName>code_type</ColumnName>

      <DataType>varchar</DataType>

      <IsAnsiPadded>1</IsAnsiPadded>

    </Column>

  </Columns>

 

Table Definition Note 5

This will be an XML-formatted list of the collations found using logic similar to the query shown below, along with the counts of each.

 

SELECT

    ISNULL(C.collation_name, 'NULL')  AS Collation        ,

    COUNT(1)                          AS CountOfCollation

  FROM    sys.columns AS C

    JOIN  sys.objects AS O ON C.object_id = O.object_id

  WHERE O.type = 'U'

  GROUP BY ISNULL(C.collation_name, 'NULL')

  FOR XML PATH ('Collation'), ROOT ('Collations');

 

An example of the format of the XML is below. There will be 1-n Collation elements, one for each entry returned by the query above:

 

  <Collations>

    <Collation>

      <Name>NULL</Name>

      <CountOfCollation>1234</CountOfCollation>

    </Collation>

    <Collation>

      <Name>SQL_Latin1_General_CP1_CI_AS</Name>

      <CountOfCollation>5678</CountOfCollation>

    </Collation>

  </Collations>

 

Table Definition Note 6

This will be an XML-formatted list of the saved settings in stored procedure definitions.

 

SELECT

    P.name, M.uses_ansi_nulls, M.uses_quoted_identifier, M.is_schema_bound,

    M.uses_database_collation, M.is_recompiled, M.null_on_null_input

  FROM    sys.sql_modules AS M

    JOIN  sys.procedures  AS P ON M.object_id = P.object_id

  WHERE P.type = 'P'

    AND P.is_ms_shipped = 0

  ORDER BY P.name

  FOR XML PATH ('Sproc'), ROOT ('Sprocs');

 

An example of the format of the XML. There will be 1-n Sproc elements, one for each entry returned by the query above:

 

  <Sprocs>

    <Sproc>

      <Name>te_abra_hours_worked</Name>

      <UsesAnsiNulls>1</UsesAnsiNulls>

      <UsesQuotedIdentifier>1</UsesQuotedIdentifier>

      <IsSchemaBound>0</IsSchemaBound>

      <UsesDatabaseCollation>0</UsesDatabaseCollation>

      <IsRecompiled>0</IsRecompiled>

      <NullOnNullInput>0</NullOnNullInput>

    </Sproc>

    <Sproc>

      <Name>te_accrual_employee_plan</Name>

      <UsesAnsiNulls>0</UsesAnsiNulls>

      <UsesQuotedIdentifier>1</UsesQuotedIdentifier>

      <IsSchemaBound>0</IsSchemaBound>

      <UsesDatabaseCollation>0</UsesDatabaseCollation>

      <IsRecompiled>0</IsRecompiled>

      <NullOnNullInput>0</NullOnNullInput>

    </Sproc>

  </Sprocs>

Table Definition Note 7

This will be an XML-formatted list of tables containing dropped columns where the indexes have not been updated to reflect the new stucture. Documentation of this SQL Server 2012 bug can be found here: https://support.microsoft.com/en-us/kb/3120595?sd=rss&spid=17645

 

SELECT DISTINCT

    OBJECT_NAME(SP.object_id) AS TableWithDroppedCols

  FROM        sys.system_internals_partition_columns  AS SIPC WITH (NOLOCK)

    JOIN      sys.partitions                          AS SP   WITH (NOLOCK) ON SIPC.partition_id = SP.partition_id

    LEFT JOIN sys.columns                             AS C                  ON SP.object_id = C.object_id

  WHERE SIPC.is_dropped = 1

    AND C.system_type_id NOT IN (48, 52, 56, 61, 62, 104, 127, 173)

  ORDER BY OBJECT_NAME(SP.object_id)

  FOR XML PATH ('TableWithDroppedCols'), ROOT ('TablesWithDroppedCols');

 

Below is an example of the format of the XML. There will be 1-n “TableWithDroppedCols” elements, one for each record returned by the query above:

 

  <TablesWithDroppedCols>

    <TableWithDroppedCols>ATableName</TableWithDroppedCols>

    <TableWithDroppedCols>TableName2</TableWithDroppedCols>

  </TablesWithDroppedCols>

 

Table Definition Note 8

This will be an XML-formatted blob containing the contents of table dbo.product_history. The following query will produce the desired data.

 

SELECT

    history_id, comments, modified_datetime, object_type, version

  FROM dbo.product_history

  ORDER BY history_id DESC

  FOR XML PATH ('entry'), ROOT ('product_history');

 

Below is an example of the format of the XML. There will be 1-n “entry” elements, one for each record returned by the query above:

 

<product_history>

  <entry>

    <history_id>238</history_id>

    <comments>Build 003</comments>

    <modified_datetime>2016-03-31T16:05:00</modified_datetime>

    <object_type>DB</object_type>

    <version>8.09.003</version>

  </entry>

  <entry>

    <history_id>237</history_id>

    <comments>Build 003</comments>

    <modified_datetime>2016-03-31T16:04:00</modified_datetime>

    <object_type>DB</object_type>

    <version>8.09.003</version>

  </entry>

  <entry>

    <history_id>236</history_id>

    <comments>Build 062</comments>

    <modified_datetime>2016-03-31T13:41:00</modified_datetime>

    <object_type>DB</object_type>

    <version>8.08.062</version>

  </entry>

</product_history>

 

Submission Script Dependencies

These are needed only in your development environments. Submission script depends on them. Download these from Project Forum.

  1. dbo.SystemSettings.sql
    SubmissionScriptDependencies.sql
    Execute BCP Output.sql
    Gather Column Data and Parse XML into Rows Without RBAR.sql (this can used directly in submission script or could be used as example for breaking huge xml into chunks of 8k text)
    Gather Sproc Data and Parse XML into Rows Without RBAR.sql (this can used directly in submission script or could be used as example for breaking huge xml into chunks of 8k text)

ELIGIBLE EVENTS:

2016 TopCoder(R) Open

Review style

Final Review

Community Review Board

Approval

User Sign-Off

ID: 30053865