.NET Framework 2.0 中,Microsoft 在 System.Data.Common 名称空间下定义了一组类用来让程序员编写适用于不同数据库的数据访问代码,而且还在 Enterprise Library 中提供了一个标准的示范。但是这里面有很大的一个问题就是当程序员使用带参sql的方式来访问数据库时,一切都变得毫无意义了。因为 SQL Server 支持以 @ 为前缀的名称参数、Oracle 则支持以 : 为前缀的名称参数,而当使用 OleDb 访问 Access 时就变成了使用 ? 作为占位符的位置参数语法。在编写程序时,必须针对不同的 ADO.NET Provider 编写 sql 语句。

本文将介绍一种方法,可以使得 SQL Server、Oracle 也支持以 ? 为占位符的位置参数语法。要想实现这个效果,就需要将 sql 语句中的 ? 占位符替换成相应的名称参数。下面以 SQL Server 数据库为例,假如有一条 sql 语句:

select count(0) from sys_user where user_code=? and password=?

如果能够将其转变为:

select count(0) from sys_user where user_code=@p1 and password=@p2

就可以使 SQL Server 也支持以 ? 为占位符的位置参数了。

在做这个变换时,我使用了一个正则表达式。通过这个正则表达式,可以将 sql 语句中的所有 ? 占位符找到,并将其替换为以 @ 为前缀的位置参数,代码如下:

private string PreparePlaceHolder(string srcSql)
{
string _sqlTokenPattern = "[\\s]+|(?<string>'([^']|'')*')|(?<comment>(/\\*([^\\*]|\\*[^/])*\\*/)|(--.*))|(?<parametermarker>\\?)|(?<query>select)|(?<identifier>([\\p{Lo}\\p{Lu}\\p{Ll}\\p{Lm}\\p{Nd}\\uff3f_#$]+)|(\"([^\"]|\"\")*\"))|(?<other>.)";
Regex sqlTokenParser = new Regex(_sqlTokenPattern, RegexOptions.ExplicitCapture); List<Group> groups = new List<Group>();
bool flag = false; for (Match match = sqlTokenParser.Match(srcSql); Match.Empty != match; match = match.NextMatch())
{
if (!match.Groups["comment"].Success)
{
if ((match.Groups["comment"].Success || match.Groups["string"].Success) || match.Groups["other"].Success)
{
flag = true;
}
else if (match.Groups["query"].Success)
{
if (!flag)
{
// 走到这里,表示这是一条 select 语句。
}
}
else if (match.Groups["parametermarker"].Success)
{
// 走到这里,表示发现了一个 ? 占位符。
groups.Add(match.Groups["parametermarker"]);
}
}
} StringBuilder desSql = new StringBuilder(srcSql); for (int i = groups.Count - ; i >= ; i--)
{
Group group = groups[i]; desSql.Remove(group.Index, group.Length);
desSql.Insert(group.Index, ParameterToken + "p" + (i + ));
}
return desSql.ToString();
}

利用上述方法,可以编写出更加通用的 SQLHelper 类。程序员可以在任何时候使用位置参数语法来执行 sql 语句,而不必考虑对应的 ADO.NET Provider 是否支持位置参数。

通过一个正则表达式,让SQL Server数据库的带参sql也支持位置参数语法!的更多相关文章

  1. SQL Server数据库性能优化之SQL语句篇【转】

    SQL Server数据库性能优化之SQL语句篇http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 近期项目需要, 做了一 ...

  2. 转载——SQL Server数据库性能优化之SQL语句篇

    转载自:http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 1. 按需索取字段,跟“SELECT *”说拜拜 字段的提取一 ...

  3. SQL SERVER数据库性能优化之SQL语句篇

    (引用自重明鸟的博客,方便学习和查看) 1. 按需索取字段,跟“SELECT *”说拜拜 字段的提取一定要按照“用多少提多少”的原则,避免使用“SELECT *”这样的操作.做了这样一个实验,表tbl ...

  4. Sql server 数据库中,纯SQL语句查询、执行 单引号问题。

    在默认值情况下, select 'abc',Titile from tb_Name;  ---输出内容 是abc: 如果想输出 单引号 'abc,需要使用select '''abc',Titile f ...

  5. SQL Server 数据库备份还原常用SQL语句及注意

    1.备份数据库 backup database db_name to disk='d:\db_name.bak' with format --通过使用with format可以做到覆盖任何现有的备份和 ...

  6. delphi连接sql server数据库,并根据sql语句查询出数据显示--初级

    需要用到四个组件,分别为: 1.ADOConnection1 设置Connectionstring属性(连接串),loginPrompt属性控制是否连接记住了密码: 2.ADOQuery1 设置Con ...

  7. 【转】PowerShell 连接SQL Server 数据库 - ADO.NET

    转至:http://www.pstips.net/connect-sql-database.html PowerShell 通过ADO.NET连接SQL Server数据库,并执行SQL脚本.工作中整 ...

  8. 5、SQL Server数据库、T-SQL

    SQL Server数据库基础 一.安装SQL Server数据库 setup.exe->安装->全新SQL Server独立安装或向现有安装添加功能->输入序列号->下一步- ...

  9. SQL Server学习之路(七):Python3操作SQL Server数据库

    0.目录 1.前言 2.准备工作 3.简单测试语句 4.提交与回滚 5.封装成类的写法 1.前言 前面学完了SQL Server的基本语法,接下来学习如何在程序中使用sql,毕竟不能在程序中使用的话, ...

随机推荐

  1. Anton and Lines(思维)

    Anton and Lines time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  2. 加濾鏡效果GlowTween

    /** * * new GlowTween(xxxx, 0xFFFF00); * new GlowTween(xxxx, 0x00FFFF); * GlowTween */ package com.r ...

  3. Backup Exec Inventory 与Catalog的含义(转载)

    编录:即catalog,就是让磁带机读取磁带之前所备份过的内容的目录列表,可以让你知道之前做过什么备份,以及备份时间等详细信息. 列清单:inventory,跟编录是不同,inventory是查询磁带 ...

  4. xcode新建项目介绍

    xcode新建项目介绍 1.打开xcode选择“create a new xcode project 2.product name 工程名称 campany identifter 公司id 一般都写公 ...

  5. JS赋值传递的问题

    根据值的类型是基本类型值还是复杂类型的值在传递时会有不同. JS函数的参数传递是按值传递,基本类型值传递的是副本,复杂类型值传递的是引用.从而会影响原来的值,不会改变原来的复制前的引用. functi ...

  6. 出现No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here异常

    问题描述: public void save(BaseEntity baseEntity) { Session session = null; try { session = currentSessi ...

  7. linux 系统分区方案建议

    前言: 以前初识Linux时,对Linux系统安装时分区的选择,一点都不了解,导致几次没法进行下一步安装,因此就静下心来,专门拿出时间研究了研究这方面的知识: 以下内容就是以前通过研究Linux安装过 ...

  8. Django模板-模板标签

    接着Django模板-基础知识继续写模板相关知识. if标签 {% if %} 标签接受 and , or 或者 not 关键字来对多个变量做判断 ,或者对变量取反( not ). 但是不允许在同一个 ...

  9. django是怎么处理请求的

    本文摘自 http://djangobook.py3k.cn/2.0/chapter03/ 我们在Django建立helloworld自定义页面中新建了站点,并能接受URL请求展示我们的页面,那Dja ...

  10. HTTP缓存缓存机制

    http协议无状态,所以缓存设定从两方面考虑.客户端浏览器和服务器端. 浏览器端实现过期机制. 服务器端实现验证机制. 缓存机制. 为了减轻服务器负担,也减少网络传输数量.http1.0定义了Expi ...