Code to validate SQL Scripts

前端 未结 4 830
挽巷
挽巷 2020-11-28 08:19

How can I validate sql scripts before executing them using .net 2.0 and c#?

If the sql is not valid I want to return error rows.

4条回答
  •  北海茫月
    2020-11-28 08:43

    I know that the question was about .NET 2.0, but it may be interesting for someone. Validation of queries has slightly changed in the latest versions of Microsoft SQL Server. The namespace is Microsoft.SqlServer.TransactSql.ScriptDom instead of Microsoft.Data.Schema.ScriptDom.

    Where to find this library?

    Path to the library is %programfiles(x86)%\Microsoft SQL Server\120\SDK\Assemblies If you cannot find this library and Microsoft SQL Server is installed, try to change from 120 to 110 or 100 and use the corresponding parser (TSql110Parser or TSql100Parser respectively).

    How to use?

    I have two extensions: the first extension checks whether the input string is a valid SQL query and the second can be used to get errors from parsing.

    using Microsoft.SqlServer.TransactSql.ScriptDom;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    
    public static class SqlStringExtensions
    {
        public static bool IsValidSql(this string str)
        {
            return !str.ValidateSql().Any();
        }
    
        public static IEnumerable ValidateSql(this string str)
        {
            if (string.IsNullOrWhiteSpace(str))
            {
                return new[] { "SQL query should be non empty." };
            }
            var parser = new TSql120Parser(false);
            IList errors;
            using (var reader = new StringReader(str))
            {
                parser.Parse(reader, out errors);
            }
            return errors.Select(err => err.Message);
        }
    }
    

    Additionaly, I check that the input SQL query is not null or empty, because the parser thinks that empty string is perfectly valid (and I don't judge it).

    How to test?

    There are three NUnit tests which show how you can use this extensions.

    using System.Collections.Generic;
    using System.Linq;
    using NUnit.Framework;
    
    [TestFixture]
    public class SqlStringExtensionsTests
    {
        [Test]
        public void ValidateSql_InvalidSql_ReturnsErrorMessages()
        {
            // this example doesn't contain "," between the field names
            string invalidSql = "SELECT /*comment*/ " +
                "CustomerID AS ID CustomerNumber FROM Customers";
            IEnumerable results = invalidSql.ValidateSql();
            Assert.AreNotEqual(0, results.Count());
        }
    
        [Test]
        public void IsValidSql_ValidSql_ReturnsTrue()
        {
            string validSql = "SELECT /*comment*/ " +
                "CustomerID AS ID, CustomerNumber FROM Customers";
            bool result = validSql.IsValidSql();
            Assert.AreEqual(true, result);
        }
    
        [Test]
        public void IsValidSql_InvalidSql_ReturnsFalse()
        {
            // this example doesn't contain "," between the field names
            string invalidSql = "SELECT /*comment*/ "+
                " CustomerID AS ID CustomerNumber FROM Customers";
            bool result = invalidSql.IsValidSql();
            Assert.AreEqual(false, result);
        }
    }
    

提交回复
热议问题