写出易调试的SQL
注意: 本文存在SQL 注入的风险, 请用做调试环境, 最终解决方法见下一篇 《写出易调试的SQL(修订版)》http://www.cnblogs.com/anuo/p/6256673.html
1.前言
相比高级语言的调试如C# , 调试SQL是件痛苦的事 . 特别是那些上千行的存储过程, 更是我等码农的噩梦.
在将上千行存储过程的SQL 分解到 C# 管理后, 也存在调试的不通畅, 如何让调试流畅些呢, 请看后续
2.常见调试
2.1 通常在Dapper 里面一个断点下去, 抓到类似如下SQL:
SELECT
a.*
FROM dbo.ptype a
INNER JOIN dbo.PType_Price b ON a.typeId=b.PTypeID
LEFT JOIN dbo.PType_Units c ON a.typeId=c.UnitsId
WHERE a.typeId=@typeid AND a.CreateDate=@Area
AND preprice1=@preprice1 AND deleted=@deleted
各种@符号, 需要手工替换后才能调试(麻烦), 要是能抓到最终SQL就好了
2.2 庆幸的是可以通过SQLServer Profiler 来抓到最终SQL
但是生产环境中的SQLServer, 并发执行的SQL 非常多, 如上图所见, 在一大堆SQL 里面找到你刚才执行的SQL也比较麻烦, 即使可以Ctrl + F 调出搜索框来搜索, 也要想个好的关键字来搜索 , 麻烦.
3.解决方案
既然我们想要最终的SQL , 为毛不在丢给Dapper 执行前, 就已经是最终SQL了呢, 上工具代码:
public class SqlHelper
{ public Dictionary<string, object> Param = new Dictionary<string, object>(); public string ReplaceParam(ref string sql)
{
if (Param.Count == )
{
return sql;
} StringBuilder sb = new StringBuilder();
sb.Append(sql);
foreach (var item in Param)
{
var paramName = item.Key;
var paramValue = item.Value;
var type = paramValue.GetType();
if (type == typeof(string) || type == typeof(DateTime))
{
//字符串
sb.Replace($"@{paramName}", $"'{paramValue}'");
}
else if (type == typeof(bool))
{
//bool 类型
if (paramValue.ToString() == "True")
{ sb.Replace($"@{paramName}", "");
}
else
{
sb.Replace($"@{paramName}", "");
}
}
else
{
//数值
sb.Replace($"@{paramName}", paramValue.ToString());
}
} sql = sb.ToString();
return sql;
}
}
调用示例:
public IEnumerable<Ptype> GetPtypeDetail()
{
var sql = @"
SELECT a.*
FROM dbo.ptype a
INNER JOIN dbo.PType_Price b ON a.typeId=b.PTypeID
LEFT JOIN dbo.PType_Units c ON a.typeId=c.UnitsId
WHERE a.typeId=@Typeid AND a.CreateDate=@CreateDate
AND preprice1=@preprice1 AND deleted=@deleted ";
var sqlHelper = new SqlHelper(); sqlHelper.Param.Add("Typeid", "");
sqlHelper.Param.Add("CreateDate", DateTime.Now);
sqlHelper.Param.Add("preprice1", 3.62M);
sqlHelper.Param.Add("deleted", true);
sqlHelper.ReplaceParam(ref sql); IEnumerable<Ptype> plist = new List<Ptype>();
using (var con = SQLServerHelper.GetConnection())
{
plist = con.Query<Ptype>(sql);
} return plist;
}
这样丢给Dapper 执行的SQL 始终是最终SQL, 就不用煞费苦心去抓了.
PS: 有人可能会质疑这样替换的效率,不用担心已测试 , C#的字符串替换是非常快的, 上面的调用实例, 当时的测试结果是 微妙和纳秒级别, 有兴趣的看管可以再测试.
4. 最后
现在丢给Dapper执行的不再是 充满@参数的SQL , 而是一个替换好的最终SQL .
这样当老板隔老远吼道你说: 小蒋, 你tm 有个XX bug ,赶紧看看 .
你可以不慌不忙的在 Dapper Query处打个断点
鼠标放在SQL变量上, 轻松的拿到最终SQL进行调试, 而不是, 手动去替换@参数, 又或则在SQLServer Profiler 里面大海捞针了!!!
作者: 蒋奎
博客: http://www.cnblogs.com/anuo/
欢迎转载,请在明显位置给出出处及链接
写出易调试的SQL的更多相关文章
- 写出易调试的SQL(修订版)
h4 { background: #698B22 !important; color: #FFFFFF; font-family: "微软雅黑", "宋体", ...
- 写出易调试的SQL—西科软件
1.前言 上篇 写出易调试的SQL , 带来了一些讨论, 暴露了不能重用执行计划和sql注入问题, 十分感谢园友们的建议 . 经过调整后 ,将原来的SQLHelper 抓SQL 用做调试环境用, 发布 ...
- 写出易于调试的SQL
1.前言 相比高级语言的调试如C# , 调试SQL是件痛苦的事 . 特别是那些上千行的存储过程, 更是我等码农的噩梦. 在将上千行存储过程的SQL 分解到 C# 管理后, 也存在调试的不通畅, 如何让 ...
- 如何写出性能好的sql
开发人员是很少注意SQL对数据库性能影响的重要性的,大多程序员都会认为SQL是比较简单的,需要的时候查查手册就可以了,很少有深究的. 这样的观念对大型系统的开发是致命的,需要纠正这样的观念. 造成这样 ...
- Mysql写出高质量的sql语句的几点建议
CleverCode在实际的工作也写过一些低效率的sql语句.这些语句会给数据库带来非常大的压力.最基本的表现就是sql语句执行慢,后来逐渐的去优化和尝试. 总结了一些高质量的sql语句的写法.这里C ...
- Oracle 如何写出高效的 SQL
转自:Oracle 如何写出高效的 SQL 要想写出高效的SQL 语句需要掌握一些基本原则,如果你违反了这些原则,一般情况下SQL 的性能将会很差. 1. 减少数据库访问次数连接数据库是非常耗时的,虽 ...
- SQL SERVER全面优化-------写出好语句是习惯
前几篇文章已经从整体提供了诊断数据库的各个方面问题的基本思路...也许对你很有用,也许你觉得离自己太远.那么今天我们从语句的一些优化写法及一些简单优化方法做一个介绍.这对于很多开发人员来说还是很有用的 ...
- Oracle如何写出高效的SQL
转载:http://www.blogjava.net/ashutc/archive/2009/07/19/277215.html 1.选择最有效率的表明顺序(只在基于规则的优化器中有效) Oracle ...
- [转]如何写出高效能TSQL -深入浅出SQL Server Relational Engine (含 SQL 2014 in-memory Engine)
[转]如何写出高效能TSQL -深入浅出SQL Server Relational Engine (含 SQL 2014 in-memory Engine) http://blogs.technet. ...
随机推荐
- LINUX篇,设置MYSQL远程访问实用版
每次设置root和远程访问都容易出现问题, 总结了个通用方法, 关键在于实用 step1: # mysql -u root mysql mysql> Grant all privileges o ...
- H5坦克大战之【建造敌人的坦克】
公司这几天在准备新版本的上线,今天才忙里偷闲来写这篇博客.接着上一篇的"H5坦克大战之[玩家控制坦克移动2]"(http://www.cnblogs.com/zhouhuan/ ...
- Spark踩坑记——Spark Streaming+Kafka
[TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...
- 关于python的bottle框架跨域请求报错问题的处理
在用python的bottle框架开发时,前端使用ajax跨域访问时,js代码老是进入不了success,而是进入了error,而返回的状态却是200.url直接在浏览器访问也是正常的,浏览器按F12 ...
- iOS逆向工程之Hopper中的ARM指令
虽然前段时间ARM被日本软银收购了,但是科技是无国界的,所以呢ARM相关知识该学的学.现在看ARM指令集还是倍感亲切的,毕竟大学里开了ARM这门课,并且做了不少的实验,当时自我感觉ARM这门课学的还是 ...
- CRL快速开发框架系列教程七(使用事务)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- H5 canvas的 width、height 与style中宽高的区别
Canvas 的width height属性 1.当使用width height属性时,显示正常不会被拉伸:如下 <canvas id="mycanvas" width=&q ...
- iOS:以前笔记,未整理版。太多了,先放着吧。。。。。。。
1. -(void)timetick { _d = 0; NSTimer *newtime =[NSTimer scheduledTimerWithTimeInterval:1 target:self ...
- Ubuntu设置root用户登录图形界面
Ubuntu默认的是root用户不能登录图形界面的,只能以其他用户登录图形界面.这样就很麻烦,因为权限的问题,不能随意复制删除文件,用gedit编辑文件时经常不能保存,只能用vim去编辑. 解决的办法 ...
- linux-centos在VM中的网络配置
1.自动获取IP地址 虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分配IP地址. #dhclient 自动获取ip地址命令 #ifconfig 查询系统里网卡信息,i ...