应用系统如何分析和获取SQL语句的执行代码

大部分开发人员都有这样一个需求,在程序连接数据库执行时,有时需要获取具体的执行语句,以便进行相关分析,这次我向大家介绍一下通用权限管理系统提供的SQL语句执行跟踪记录,直接先看看代码吧:(这个功能我也是在看底层代码时发现的)

namespace DotNet.Utilities
{
    /// <summary>
    /// SQLTrace
    /// 记录SQL执行 Global 中设置 BaseSystemInfo.LogSQL=true 可以开启跟踪记录
    ///
    ///
    /// 修改纪录
    ///
    ///        2016.01.12 版本:1.0    SongBiao
    ///
    /// <author>
    ///        <name>SongBiao</name>
    ///        <date>2016.01.12</date>
    /// </author>
    /// </summary>
    public class SQLTrace
    {
        private static string FileName = "SQLTrace.txt";

        #region public static void WriteLog(string commandText,IDbDataParameter[] dbParameters = null,  string fileName = null) 写入sql查询句日志
        /// <summary>
        /// 写入sql查询句日志
        /// </summary>
        /// <param name="commandText">异常</param>
        /// <param name="dbParameters"></param>
        /// <param name="fileName">文件名</param>
        public static void WriteLog(string commandText, IDbDataParameter[] dbParameters = null, string fileName = null)
        {
            // 系统里应该可以配置是否记录异常现象
            if (!BaseSystemInfo.LogSQL)
            {
                return;
            }
            if (string.IsNullOrEmpty(fileName))
            {
                fileName = DateTime.Now.ToString(BaseSystemInfo.DateFormat) + " _ " + FileName;
            }
            string message = string.Empty;
            message = DateTime.Now.ToString(BaseSystemInfo.DateTimeFormat) + System.Environment.NewLine + "commandText内容" + System.Environment.NewLine + commandText;
            if (dbParameters != null)
            {
                StringBuilder sb = new StringBuilder();
                foreach (var parameter in dbParameters)
                {
                    sb.AppendLine(parameter.ParameterName + "=" + parameter.Value);
                }
                message += System.Environment.NewLine + "dbParameters内容" + System.Environment.NewLine + sb.ToString();
            }
            // 将异常信息写入本地文件中
            string logDirectory = BaseSystemInfo.StartupPath + @"\Log\Query";
            if (!System.IO.Directory.Exists(logDirectory))
            {
                System.IO.Directory.CreateDirectory(logDirectory);
            }
            string writerFileName = logDirectory + "\\" + fileName;
            FileUtil.WriteMessage(message, writerFileName);
        }
        #endregion
    }
}

方法比较简单,传入参数化的SQL语句及参数数组,就可以在文件中记录每次具体的操作语句。如下图:(访问的是MySQL数据库)

【通用权限管理系统中获取某个用户具有的权限(数组)的语句,记录了CommandText和dbParameters两部分,拼接一下就可以执行了】

大家可以参照这个,写出对应的方法记录自己程序访问数据库的语句。

我们来看看在通用权限底层是如何调用这个功能的:

1、在应用程序的Global中加入以下语句,开启日志记录及存储位置设置

            BaseSystemInfo.StartupPath = HttpContext.Current.Server.MapPath("~/");
            BaseSystemInfo.LogSQL = true;

如下图

2、调用的一个地方参考

        #region public virtual DataSet Fill(DataSet dataSet, string commandText, string tableName, IDbDataParameter[] dbParameters, CommandType commandType) 填充数据权限
        /// <summary>
        /// 填充数据权限
        /// </summary>
        /// <param name="dataSet">数据权限</param>
        /// <param name="commandType">命令分类</param>
        /// <param name="commandText">sql查询</param>
        /// <param name="tableName">填充表</param>
        /// <param name="dbParameters">参数集</param>
        /// <returns>数据权限</returns>
        public virtual DataSet Fill(DataSet dataSet, string commandText, string tableName, IDbDataParameter[] dbParameters, CommandType commandType)
        {
            // 自动打开
            if (this.DbConnection == null)
            {
                this.Open();
                this.MustCloseConnection = true;
            }
            else if (this.DbConnection.State == ConnectionState.Closed)
            {
                this.Open();
                this.MustCloseConnection = true;
            }

            using (this.dbCommand = this.DbConnection.CreateCommand())
            {
                this.dbCommand.CommandTimeout = this.DbConnection.ConnectionTimeout;
                this.dbCommand.CommandText = commandText;
                this.dbCommand.CommandType = commandType;
                if (this.dbTransaction != null)
                {
                    this.dbCommand.Transaction = this.dbTransaction;
                }

                if ((dbParameters != null) && (dbParameters.Length > 0))
                {
                    for (int i = 0; i < dbParameters.Length; i++)
                    {
                        if (dbParameters[i] != null)
                        {
                            this.dbCommand.Parameters.Add(((ICloneable)dbParameters[i]).Clone());
                        }
                    }

                }

                this.dbDataAdapter = this.GetInstance().CreateDataAdapter();
                this.dbDataAdapter.SelectCommand = this.dbCommand;
                this.dbDataAdapter.Fill(dataSet, tableName);

                SetBackParamValue(dbParameters);

                if (this.MustCloseConnection)
                {
                    this.Close();
                }
                else
                {
                    this.dbDataAdapter.SelectCommand.Parameters.Clear();
                }
            }

            // 记录日志
            SQLTrace.WriteLog(commandText, dbParameters);

            return dataSet;
        }
        #endregion

这个功能好好利用,对于分析系统的SQL执行是非常方便的。

时间: 2024-12-18 06:56:20

应用系统如何分析和获取SQL语句的执行代码的相关文章

sql语句的执行原理

SQL语句执行过程详解 2014-07-17 01:15:43 分类: Oracle SQL语句执行过程详解一条sql,plsql的执行到底是怎样执行的呢?一.SQL语句执行原理:第一步:客户端把语句发给服务器端执行当我们在客户端执行 select 语句时,客户端会把这条 SQL 语句发送给服务器端,让服务器端的进程来处理这语句.也就是说,Oracle 客户端是不会做任何的操作,他的主要任务就是把客户端产生的一些 SQL 语句发送给服务器端.虽然在客户端也有一个数据库进程,但是,这个进程的作用跟

SQL语句的执行顺序和效率

今天上午在开发的过程中,突然遇到一个问题,需要了解SQL语句的执行顺序才能继续,上网上查了一下相关的资料,现整理如下:一.sql语句的执行步骤: 1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义. 2) 语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限. 3)视图转换,将涉及视图的查询语句转换为相应的对基表查询语句. 4)表达式转换, 将复杂的 SQL 表达式转换为较简单的等效连接表达式. 5)选择优化器,不同的优化器一般产生不同的"执行计划" 6

ORACLE数据库SQL语句的执行过程

首先是最简单链接数据库的过程,JDBC标准的链接的过程: 1. 载入JDBC驱动程序,一般来说载入驱动程序,采用的都是利用Class.forName()反射来加载驱动 Oracle: Class.forName("oracle.jdbc.driver.OracleDriver"); SQLServer: Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); MySql: Class.forNam

mysql(1)—— 详解一条sql语句的执行过程

SQL是一套标准,全称结构化查询语言,是用来完成和数据库之间的通信的编程语言,SQL语言是脚本语言,直接运行在数据库上.同时,SQL语句与数据在数据库上的存储方式无关,只是不同的数据库对于同一条SQL语句的底层实现不同罢了,但结果相同.这有点类似于java中接口的作用,一个接口可以有不同的实现类,不同的实现类对于接口中方法的实现方式可以不同,结果可以相同.这里SQL语言的作用就类似于java中的接口,数据库就类似于java中接口的实现类,SQL语句就类似于java接口中的方法.不同的是java中

SQL 语句的执行顺序

写在前面的话:有时不理解SQL语句各个部分执行顺序,导致理解上出现偏差,或者是书写SQL语句时随心所欲,所以有必要了解一下sql语句的执行顺序.可以有时间自己写一个简单的数据库,理解会更加深入.下面就写写我的一些理解,以SQL SERVER2008为例,进行说明. 先看下面这条简单SQL语句: 1 select 2 top 10 * 3 from Student 4 where age>20 这条SQL语句是否可以有下面两种理解呢 (1)先从Student表中选出age>20的数据,然后从这些

详解一条sql语句的执行过程

SQL是一套标准,全称结构化查询语言,是用来完成和数据库之间的通信的编程语言,SQL语言是脚本语言,直接运行在数据库上.同时,SQL语句与数据在数据库上的存储方式无关,只是不同的数据库对于同一条SQL语句的底层实现不同罢了,但结果相同.这有点类似于java中接口的作用,一个接口可以有不同的实现类,不同的实现类对于接口中方法的实现方式可以不同,结果可以相同.这里SQL语言的作用就类似于java中的接口,数据库就类似于java中接口的实现类,SQL语句就类似于java接口中的方法.不同的是java中

查询Oracle正在执行的sql语句及执行该语句的用户

查询Oracle正在执行的sql语句及执行该语句的用户SELECT B.SID ORACLEID,B.USERNAME 登录ORACLE用户名,B.SERIAL#,SPID 操作系统ID,PADDR,SQL_TEXT 正在执行的SQL,B.MACHINE 计算机名FROM V$PROCESS A, V$SESSION B, V$SQLAREA CWHERE A.ADDR = B.PADDRAND B.SQL_HASH_VALUE = C.HASH_VALUE; --查看正在执行sql的发起者的发

Sql Server 优化----SQL语句的执行方式与锁以及阻塞的关系

阻塞原因之一是不同的Session在访问同一张表的时候因为不兼容锁的原因造成的, 当前执行的SQL语句是否被阻塞(或者死锁),不仅跟当前表上的已有的锁有关,也会跟当前执行的SQL语句的执行方式有关 简单来说,对于表的访问方式,SQL语句的执行无非是表扫描,索引扫描,(聚集索引或者非聚集索引)索引查找等等 如果SQL语句的执行方式不当或者没有合理的索引,会造成没必要的阻塞,如果逻辑控制不当,甚至造成更严重的问题,造成数据逻辑的错误 建个测试表,下面测试演示一下 create table testI

程序中使用事务来管理sql语句的执行,执行失败时,可以达到回滚的要求。

1.设置使用事务的SQL执行语句 1 /// <summary> 2 /// 使用有事务的SQL语句 3 /// </summary> 4 /// <param name="sql"></param> 5 /// <param name="conn"></param> 6 /// <param name="tran"></param> 7 /// &l