SqlServer参数化查询之where in和like实现之xml和Data
在之前的文章《Sql Server参数化查询之where in和like实现详解》中,我们了Sql Server中参数化查询的几种实现方案,其中涉及了where in的多种应用策略。我们在之前的分享中遗漏了关于xml和表值参数的讨论,今天我们来详细补充一下。
方案五:利用XML参数进行where in查询。在这之前,你需要对XQuery有一个基本的了解。XQuery是一种用于从XML文档中查找和提取元素及属性的语言。为了更好地理解这个概念,你需要知道XPath,它是XQuery的一个子集。XQuery 1.0和XPath 2.0共享相同的数据模型,支持相同的函数和运算符。如果你已经掌握了XPath的知识,学习XQuery将会更加轻松。关于它们的详细概念,建议进一步学习。
在Sql Server中,当我们谈论XML参数时,我们需要了解Sql Server对XML的支持函数。这些函数包括……,对于具体的函数和使用方法,需要进一步的研究和了解。
接下来,我们来讨论如何使用XML方式实现where in查询。这里有两种主要的实现方式:使用value和exist。在这里,我们推荐使用exist方法。
MSDN对这两种方法的描述是这样的:在使用exist方法时,我们避免在谓词中使用value方法与关系值进行比较,而是选择使用带有sql:column()的exist()方法。这样做主要是出于性能考虑。exist方法能够更好地处理XML数据,并且在查询大型XML文档时表现出更好的性能。
利用XML的value方法与exist方法实现数据库查询
在数据库操作中,我们常常需要处理XML数据,这时利用SQL对XML的处理能力就显得尤为重要。虽然value方法和exist方法都可以实现这一目的,但在实际使用中,它们的表现有所差异。今天,我们将深入这两种方法,并分享不同XML结构下的查询方法示例。
让我们看看不推荐使用value方法实现的原因。虽然value方法可以从XML片段中提取数据,但它的性能相对exist方法较低。例如,当我们有如下的XML结构时:
```xml
```
使用value方法的查询示例可能如下:
```sql
select from Users
where exists (
select 1 from @xml.nodes('/root/UserID') as T(c)
where T.c.value('text()[1]','int') = Users.UserID
)
```
相比之下,使用exist方法实现则能带来更高的性能。同样的XML结构下,使用exist方法的查询示例如下:
```sql
select from Users
where @xml.exist('/root/UserID[text()=sql:column("UserID")]')=1
```
在实际应用中,我们可能会遇到不同的XML结构。例如,一个包含用户信息的XML结构可能如下:
```xml
```
对于此种结构,我们可以这样使用value方法查询:
```sql
select from Users
where UserID in (
select T.c.value('UserID[1]','int') from @xml.nodes('/root/User') as T(c)
)
```
而使用exist方法的查询则可能如下:
```sql
select from Users
where @xml.exist('/root/User[UserID=sql:column("UserID")]')=1
``` 需要注意的是在使用XML参数时的一些要点:不同于SQL语句默认不区分大小写,XML的XQuery表达式是严格区分大小写的。在书写时一定要注意大小写问题。在使用exist方法时,sql:column()中的列名必须使用双引号。如果需要用到单引号,则需要连续输入两个单引号,如 `sql:column(''UserID'')`。在进行XML查询时,尤其是在处理大量数据时,推荐使用exist方法以提高性能。尽管性能优化可能并不总是显而易见,但任何可以提升效率的机会都不应被忽视。在实际应用中根据XML结构灵活选择使用value或exist方法,确保查询的准确性和效率。表值参数(Table-Valued Parameters,简称TVP)在Sql Server 2008中引入,为大数据量处理提供了一种高效的解决方案。特别是在数据量小于一千时,TVP参数展现出卓越的性能。本文将详细介绍如何使用TVP来实现DataTable集合传参,特别是在实现“where in”查询时的应用。
我们需要在数据库中创建一个表值函数。例如:
```sql
create type IntCollectionTVP as Table(ID int)
```
接下来,在C中调用此表值函数。主要注意点包括:
1. 在SqlParameter中,需要将SqlDbType设置为SqlDbType.Structured,并设置TypeName为在数据库中创建的表值函数名。在本例中,TypeName为“IntCollectionTVP”。
2. 构造的DataTable列数必须和表值函数定义的一致。虽然具体列名可以随意,但建议数据类型与表值类型定义保持一致,以避免隐式类型转换和提高性能。
3. 查询条件中的类型应与TVP对应字段类型一致,以规避隐式类型转换带来的性能损失。
以下是使用TVP实现“where in”查询的示例代码:
```csharp
DataTable resultDt = new DataTable();
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlCommand m = conn.CreateCommand();
mmandText = @"select from Users(nolock) where exists ( select 1 from @MyTvp tvp where tvp.ID=Users.UserID )";
//构造需要传参的TVP DataTable
DataTable tvpDt = new DataTable();
tvpDt.Columns.Add("myid", typeof(int)); //添加列,列数与IntCollectionTVP保持一致
tvpDt.Rows.Add(1); tvpDt.Rows.Add(2); tvpDt.Rows.Add(3); tvpDt.Rows.Add(4); //添加数据
//添加SqlParameter,其中TypeName对应我们定义的表值函数名
m.Parameters.Add(new SqlParameter("@MyTvp", SqlDbType.Structured) { Value = tvpDt, TypeName = "IntCollectionTVP" });
using (SqlDataAdapter adapter = new SqlDataAdapter(m))
{
adapter.SelectCommand = m;
adapter.Fill(resultDt);
}
}
```
关于参数化查询中的“where in”实现,共有六种方法。其中,方法1(使用CHARINDEX或like实现)可能会完全弃用索引,若无特殊需要不建议采用。方法2(使用exec动态执行SQL)本质上与直接拼接SQL无异,可能并不实用。方法3(为每一个参数生成一个参数)受参数个数限制,且参数过多时性能待验证。方法4(使用临时表)可以替换为表变量以提高性能,但写法可能较繁琐。方法5(使用xml参数)性能应该不错,且相比拼接SQL有很大提升。方法6(使用TVP)是本文的重点,它在Sql Server 2008后可用,性能强大,特别适合处理大数据量。
每种方法都有其适用场景和优缺点,应根据实际情况选择合适的方法。
微信营销
- SqlServer参数化查询之where in和like实现之xml和Data
- PHP学习记录之面向对象(Object-oriented programming,
- 简洁实用的BootStrap jQuery手风琴插件
- BootStrap学习笔记之nav导航栏和面包屑导航
- ASP编程入门进阶(九):内置对象Application
- StringBuider 在什么条件下、如何使用效率更高
- PHP写微信公众号文章页采集方法
- PHP常用header头定义代码示例汇总
- PHP实现的统计数据功能详解
- nodejs调取微信收货地址的方法
- 数据转换冲突及转换过程中大对象的处理
- BootStrap 实现各种样式的进度条效果
- jsp网页计数器实现示例
- 基于PHP常用字符串的总结(待续)
- 浅谈javascript的call()、apply()、bind()的用法
- Vue.js -- 过滤器使用总结