Quantcast
Channel: SQL Server Blog
Viewing all articles
Browse latest Browse all 1849

A Program to Find INSERT Statements That Don’t Specify Columns

$
0
0

Unlike mathematical relations, SQL tables have ordered columns, but please don’t depend on it.
In other words, try to treat these tables as the same because it’s super-awkward to turn one into the other:

CREATETABLE PEOPLE
(
    LastName varchar(200),
    FirstName varchar(200))
CREATETABLE PEOPLE
(
    FirstName varchar(200),
    LastName varchar(200))

Don’t Omit Column Specification

And don’t forget to specify the columns in your INSERT statement. No excuses.

All the columns!

You’re depending on the column ordering if you write INSERT statements like this:

INSERT PEOPLE /* no column spec */VALUES('Rob', 'Farley'),
       ('Angela', 'Henry'),
       ('Andy', 'Leonard'),
       ('Richard', 'Douglas'),
       ('David', 'Maxwell'),
       ('Aaron', 'Nelson'),
       ('Paul', 'Randal');

We recently got burned by something like this

Find Missing Column Specifications

Thomas LaRock recently encouraged DBAs to branch out horizontally. In that spirit, don’t be too afraid of the C#. I’ve got a program here that finds procedures with missing column specifications.

  • If for some reason, you don’t care about enforcing this rule for temp tables and table variables, then uncomment the line // visitor.TolerateTempTables = true;
  • It uses ScriptDom which you can get from Microsoft as a nuget package.
  • The performance is terrible in Visual Studio because ScriptDom uses Antlr which uses exceptions for flow control and this leads to lots of “first chance exceptions” which slows down debugging. Outside of Visual Studio, it’s just fine.
usingSystem;usingSystem.Collections.Generic;usingSystem.Data.SqlClient;usingSystem.Linq;usingMicrosoft.SqlServer.TransactSql.ScriptDom; 
class Program { 
    staticvoid Main(string[] args){ 
        SqlConnectionStringBuilder builder =new SqlConnectionStringBuilder {
            DataSource =".",
            InitialCatalog ="test_database",
            IntegratedSecurity =true}; 
        using(SqlConnection conn =new SqlConnection(builder.ToString())){
            conn.Open();
            SqlCommand command =new SqlCommand(@"
                SELECT OBJECT_SCHEMA_NAME(object_id) [schema], 
                       OBJECT_NAME(object_id)        [procedure], 
                       OBJECT_DEFINITION(object_id)  [sql]
                  FROM sys.procedures 
                 ORDER BY OBJECT_SCHEMA_NAME(object_id), OBJECT_NAME(object_id) ;", conn);
            SqlDataReader reader = command.ExecuteReader();while(reader.Read()){string schema = reader["schema"].ToString();string procedure = reader["procedure"].ToString();string sql = reader["sql"].ToString();if(SqlHasInsertWithoutColumnList(sql)){
                    Console.WriteLine( $"{schema}.{procedure}");}}}} 
    staticbool SqlHasInsertWithoutColumnList(string SQL){
        SQLVisitor visitor =new SQLVisitor();// visitor.TolerateTempTables = true;
        TSql130Parser parser =new TSql130Parser(true);
        IList<ParseError> errors;var fragment = parser.Parse(newSystem.IO.StringReader(SQL), out errors);
        fragment.Accept(visitor);return visitor.HasInsertWithoutColumnSpecification;}} 
internalclass SQLVisitor : TSqlFragmentVisitor {publicbool HasInsertWithoutColumnSpecification {get;set;}publicbool TolerateTempTables {get;set;} 
    publicoverridevoid ExplicitVisit(InsertStatement node){if(node.InsertSpecification.Columns.Any())return; 
        var source = node.InsertSpecification.InsertSourceas ValuesInsertSource;if(source !=null&& source.IsDefaultValues)return; 
        if(TolerateTempTables){var target = node.InsertSpecification.Targetas NamedTableReference;if(target !=null&&!target.SchemaObject.BaseIdentifier.Value.StartsWith("#")){
                HasInsertWithoutColumnSpecification =true;}}else{
            HasInsertWithoutColumnSpecification =true;}}}

In my environment, I found twelve examples which I’ll be fixing soon.


Viewing all articles
Browse latest Browse all 1849

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>