网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > 数据库 > SQL技巧
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
数据库:数据库教程,数据库技巧,Oracle教程,MySQL教程,Sybase教程,Access教程,DB2教程,数据库安全,数据库文摘
本月文章推荐
.SQL Server里函数的两种用法(可.
.SQL语句优化技术分析.
.SQL Server导入excel数据之Bug!.
.让SQL Server为工作负载高峰提前.
.用共享游标提升 SQL 性能.
.sql server 2000数据库置疑的解决.
.SQL Server中索引使用及维护.
.SELECT查询的应用(三).
.最新分页存储过程(增加了选择字.
.讲解数据库及数据仓库建模方法的.
.讲解SQL Server定时作业job的设置.
.dp备份检查时发现有session报错的.
.sql server关于函数中如何使用Ge.
.SQL Server 2008性能和扩展.
.讲解InfoPlus与Uniformance PHD的.
.优化方案:ETL的过程原理和数据仓.
.数据库的分页问题.
.SQL技巧:快速掌握一些异常精妙的.
.SQL语句的自动优化.
.如何在 SQL Server 2005 中使用 .

SQL Server 2008表值参数的创建和使用步骤

发表日期:2008-6-11


表值参数(Table-valued parameter)是SQL Server数据库2008的新特性之一,在以往的版本中,我们没有办法把表变量当作一个参数传递给存储过程。但在微软的SQL Server 2008中引入了表值参数这个特性,它可以实现此类功能。

表值参数有两个明显的优点:

1:不需要为初始的数据加锁。

2:它不会导致语句重新编译。

表值参数的创建和使用包括以下步骤:

(1) 创建表类型

(2) 创建一个可将表类型作为参数来接受的存储过程或函数

(3) 创建表变量并插入数据

(4) 调用该存储过程和函数,并将表变量作为参数传递。

下面,我们来一步步分解这个创建和使用的过程。首先,我们用以下的DDL SQL语句来创建一个名为“TestDB”的测试数据库:

USE [master]
GO

IF EXISTS (SELECT name FROM sys.databases WHERE name = N'TestDB')

DROP DATABASE TestDB
GO
Create database TestDB
go

下面,使用以下的DDL SQL语句来创建一个名为TestLocationTable的表:

USE [TestDB] 
GO 

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].

[TestLocationTable]') AND type in (N'U')) 

DROP TABLE [dbo].[TestLocationTable] 
GO 
USE [TestDB] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
SET ANSI_PADDING ON 
GO 
CREATE TABLE [dbo].[TestLocationTable]( 
[Id] [int] NULL, 
[shortname] [char](3) NULL, 
[name] [varchar](100) NULL 
) ON [PRIMARY] 
GO 
SET ANSI_PADDING OFF 
GO

然后,使用以下的DML SQL语句将数据添加到我们上面创建的表中:

USE [TestDB] 
GO 
insert into TestLocationTable ( Id, shortname, Name) select 1, 'NA1', 'NewYork' 
insert into TestLocationTable ( Id, shortname, Name) select 2, 'NA2', 'NewYork' 
insert into TestLocationTable ( Id, shortname, Name) select 3, 'NA3', 'NewYork' 
insert into TestLocationTable ( Id, shortname, Name) select 4, 'EU1', 'London' 
insert into TestLocationTable ( Id, shortname, Name) select 5, 'EU2', 'London' 
insert into TestLocationTable ( Id, shortname, Name) select 6, 'AS1', 'Tokyo' 
insert into TestLocationTable ( Id, shortname, Name) select 7, 'AS2', 'HongKong' 
go

下面,我们需要创建一个和TestLocationTable表具有相似表结构的表类型(TABLE TYPE),语句如下所示:

USE [TestDB] 
GO 
IF EXISTS (SELECT * FROM sys.types st JOIN sys.schemas ss ON st.schema_id = ss.schema_id 
WHERE st.name = N'OfficeLocation_Tabetype' AND ss.name = N'dbo') 
DROP TYPE [dbo].[OfficeLocation_Tabetype] 
GO 
USE [TestDB] 
GO 
CREATE TYPE [dbo].[OfficeLocation_Tabetype] AS TABLE( 
[Id] [int] NULL, 
[shortname] [char](3) NULL, 
[name] [varchar](100) NULL 
) 
GO

接下来,需要创建一个可以将表类型作为一个参数来接受的存储过程,使用的语句如下:

USE [TestDB] 
GO 
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].

[usp_InsertProdLocation]') AND type in (N'P', N'PC')) 

DROP PROCEDURE [dbo].[usp_selectProdLocation] 
GO 
CREATE PROCEDURE usp_InsertProdLocation 
@TVP OfficeLocation_Tabetype READONLY 
AS 
SET NOCOUNT ON 
INSERT INTO TestLocationTable Select ID, shortname, name from @TVP 
where convert(varchar(10),id)+shortname+name not in (select 
convert(varchar(10),id)+shortname+name from TestLocationTable) 
GO

此存储过程将表变量作为导入值接收,并且只插入TestLocationTable中没有的数据。现在,大家可以尝试创建一个表变量,并执行上面创建的存储过程usp_InsertProdLocation,语句如下所示:

use TestDB 
go 
DECLARE @TV AS [OfficeLocation_Tabetype] 
INSERT INTO @TV (Id, Shortname, Name) SELECT 12, 'ME1', 'Dubai' 
INSERT INTO @TV (Id, Shortname, Name) SELECT 13, 'ME2', 'Tehran' 
INSERT INTO @TV (Id, Shortname, Name) SELECT 17, 'EA1', 'Bombay' 
INSERT INTO @TV (Id, Shortname, Name) SELECT 18, 'EA2', 'Karachi' 
INSERT INTO @TV (Id, Shortname, Name) SELECT 3, 'NA3', 'NewYork' 
INSERT INTO @TV (Id, Shortname, Name) SELECT 4, 'EU1', 'London' 
exec usp_InsertProdLocation @TV 
go

此时,可以使用以下的TSQL语句从表TestLocationTable查询所有的数据:

use TestDB 
go 
select * from TestLocationTable 
go

查询的结果:

Id, shortname, name 
1, NA1, NewYork 
2, NA2, NewYork 
3, NA3, NewYork 
4, EU1, London 
5, EU2, London 
6, AS1, Tokyo 
7, AS2, HongKong 
12, ME1, Dubai 
13, ME2, Tehran 
17, EA1, Bombay 
18, EA2, Karachi 
(11 row(s) affected)

从返回的结果看,存储过程usp_InsertProdLocation 插入了表变量@TV中和表TestLocationTable所有不匹配的行。

另外,我们还可以将表变量传递给一个函数。下面创建一个简单的函数,语句如下所示:

USE [TestDB] 
GO 
IF EXISTS (SELECT * FROM sys.objects

WHERE object_id = OBJECT_ID(N'[dbo].[myfunction]') 

AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
 
DROP FUNCTION [dbo].[myfunction] 
GO 
create function dbo.myfunction (@TV OfficeLocation_Tabetype READONLY) 
returns int 
as 
begin 
declare @i int 
set @i=(Select COUNT(*) from @TV) 
return @i 
end

现在,大家可以通过创建一个表变量并将该变量作为一个参数传递给已创建的函数以调用该函数,该语句如下所示:

USE [TestDB] 
GO 
DECLARE @TV AS [OfficeLocation_Tabetype] 
INSERT INTO @TV (Id, Shortname, Name) SELECT 12,'ME1','Dubai' 
INSERT INTO @TV (Id, Shortname, Name) SELECT 13,'ME2','Tehran' 
INSERT INTO @TV (Id, Shortname, Name) SELECT 17,'EA1','Bombay' 
INSERT INTO @TV (Id, Shortname, Name) SELECT 18,'EA2','Karachi' 
INSERT INTO @TV (Id, Shortname, Name) SELECT 3,'NA3','NewYork' 
INSERT INTO @TV (Id, Shortname, Name) SELECT 4,'EU1','London' 
select dbo.myfunction(@TV) 
go

执行的结果:

(1 row(s) affected) 
(1 row(s) affected) 
(1 row(s) affected) 
(1 row(s) affected) 
(1 row(s) affected) 
(1 row(s) affected) 
----------- 
6

注释:上文中的参考脚本已在SQL Server 2008 CTP6版本上进行编写并已经测试成功。

上一篇:在SQL Server 2005数据库中更改数据架构 人气:1098
下一篇:讲解孤立用户和对象名无效问题的解决方法 人气:969
浏览全部SQL Server 2008的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐