SQL Server 2008使用自定义表类型

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,基础系列 2核4GB
简介: 本文转载:http://www.cnblogs.com/chenxizhang/archive/2009/04/28/1445234.html 在 SQL Server 2008 中,用户定义表类型是指用户所定义的表示表结构定义的类型。

本文转载:http://www.cnblogs.com/chenxizhang/archive/2009/04/28/1445234.html

 

在 SQL Server 2008 中,用户定义表类型是指用户所定义的表示表结构定义的类型。您可以使用用户定义表类型为存储过程或函数声明表值参数,或者声明您要在批处理中或在存储过程或函数的主体中使用的表变量。有关如何定义表结构的详细信息,请参阅 CREATE TABLE (Transact-SQL)

若要创建用户定义表类型,请使用 CREATE TYPE 语句。为了确保用户定义表类型的数据满足特定要求,您可以对用户定义表类型创建唯一约束和主键。

有关与用户定义类型相关联的目录视图的信息,请参阅 sys.typessys.table_types

限制

用户定义表类型具有下列限制:

  • 用户定义表类型不能用作表中的列或结构化用户定义类型中的字段。
  • 基于用户定义表类型的别名类型
  • [NOT FOR REPLICATION] 选项是不允许的。
  • CHECK 约束要求保留计算列。
  • 计算列的主键必须是 PERSISTED 和 NOT NULL。
  • 无法对用户定义表类型创建非聚集索引,除非该索引是对用户定义表类型创建 PRIMARY KEY 或 UNIQUE 约束的结果。(SQL Server 使用索引强制实施任何 UNIQUE 或 PRIMARY KEY 约束。)
  • 不能在用户定义表类型的定义中指定 DEFAULT 值。
  • 在创建用户定义表类型定义后不能对其进行修改。
  • 不能在用户定义表类型的计算列的定义中调用用户定义函数。

安全性

用户定义表类型的权限通过使用下列 Transact-SQL 关键字来遵循 SQL Server 的对象安全模式:CREATE、GRANT、DENY、ALTER、CONTROL、TAKE OWNERSHIP、REFERENCES、EXECUTE、VIEW DEFINITION 和 REVOKE。

 

下面我用一个实例来讲解一下

-- ================================
-- 创建和使用自定义表类型
-- 陈希章
-- ================================ 

USE master
GO
-- ================================
-- 创建测试数据库
-- ================================
CREATE DATABASE demo
GO 

-- ================================
-- 创建一个表
-- ================================
USE demo
GO 

CREATE TABLE Customers
(
    Id int NOT NULL,
    Name char(10) NULL,
    PRIMARY KEY (Id)
)
GO 

USE demo
GO
-- ================================
-- 创建自定义表类型
-- ================================
CREATE TYPE dbo.CustomerTable AS TABLE
(
    Id int NOT NULL,
    Name char(10) NULL,
    PRIMARY KEY (Id)
)
GO 

-- =================================
-- 直接使用自定义表类型
-- =================================
DECLARE @c CustomerTable
INSERT INTO @c VALUES(1,'Xizhang')
SELECT * FROM @c 

-- =================================
-- 在存储过程中使用自定义表类型
-- =================================
CREATE PROC GetCustomers
(@c CustomerTable READONLY)
AS
INSERT Customers SELECT * FROM @c --将传过来的参数(其实是一个表)的数据插入到Customers表里面去 

-- =================================
-- 调用该存储过程,一次性插入4行数据
-- =================================
DECLARE @temp CustomerTable
INSERT INTO @temp VALUES(7,'Xizhang')
INSERT INTO @temp VALUES(2,'Xizhang')
INSERT INTO @temp VALUES(3,'Xizhang')
INSERT INTO @temp VALUES(4,'Xizhang')
EXEC GetCustomers @c=@temp
SELECT * FROM Customers 

-- =================================
-- 清理数据库
-- =================================
USE master
GO 

DROP DATABASE demo
GO

看起来不错对吧,但是你应该马上想到一个问题,如果说这个存储过程要在客户端代码中调用,那么该怎么提供这个参数值呢?

using System.Data.SqlClient;
using System.Data; 

class Program
{
    static void Main(string[] args)
    {
        DataTable tb = GetData();
        using (SqlConnection conn = new SqlConnection("server=sql2008;database=demo;integrated security=true"))
        {
            using (SqlCommand cmd = conn.CreateCommand())
            {
                cmd.CommandText = "GetCustomers";
                cmd.CommandType = CommandType.StoredProcedure;
                SqlParameter param = new SqlParameter("@c", SqlDbType.Structured);//这个类型很关键
                param.Value = tb;
                cmd.Parameters.Add(param);
                conn.Open();
                cmd.ExecuteNonQuery();
                conn.Close();
            }
        } 

        Console.WriteLine("完成操作");
        Console.Read();
    } 

    private static DataTable GetData()
    {
        DataTable tb = new DataTable();
        tb.Columns.Add("Id",typeof(int));
        tb.Columns.Add("Name", typeof(string)); 

        //添加100个客户资料
        for (int i = 0; i < 100; i++)
        {
            DataRow row = tb.NewRow();
            row[0] = i;
            row[1] = "Name " + i.ToString();
            tb.Rows.Add(row);
        } 

        return tb;
    }
}

读者可能会疑惑,这样做实在是太棒了,可以一次性写入100行数据呢?我们再来看看在服务端到底发生了什么事情

image

实际上,在服务端确实会有一个定义临时变量的过程,然后把所有的数据插入到这个变量中去,然后再执行存储过程的

最后,我们可以再深入探讨探讨

1. 客户端是否一定用DataTable类型

-- 推荐使用DataTable类型,但也可以使用其他的类型,例如DataReader的数据流

2. DataTable的字段名称是否要匹配

--不一定。只要顺序一致,类型一样就可以了。

有一个参考的blog,请看下面的链接

http://msdn.microsoft.com/zh-cn/library/bb675163.aspx

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
6月前
|
SQL Java 测试技术
3、Mybatis-Plus 自定义sql语句
这篇文章介绍了如何在Mybatis-Plus框架中使用自定义SQL语句进行数据库操作。内容包括文档结构、编写mapper文件、mapper.xml文件的解释说明、在mapper接口中定义方法、在mapper.xml文件中实现接口方法的SQL语句,以及如何在单元测试中测试自定义的SQL语句,并展示了测试结果。
3、Mybatis-Plus 自定义sql语句
|
3月前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
4月前
|
SQL 数据库 开发者
功能发布-自定义SQL查询
本期主要为大家介绍ClkLog九月上线的新功能-自定义SQL查询。
|
4月前
|
SQL Java 数据库连接
mybatis使用四:dao接口参数与mapper 接口中SQL的对应和对应方式的总结,MyBatis的parameterType传入参数类型
这篇文章是关于MyBatis中DAO接口参数与Mapper接口中SQL的对应关系,以及如何使用parameterType传入参数类型的详细总结。
90 10
|
4月前
|
SQL 存储 关系型数据库
SQL判断CHAR类型字段不为空的方法与技巧
在SQL查询中,判断一个CHAR类型字段是否不为空是一个常见的需求
|
5月前
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
6月前
|
SQL 数据处理 数据库
SQL中的函数有哪些类型
【8月更文挑战第20天】SQL中的函数有哪些类型
81 1
|
7月前
|
SQL
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。
114 9
|
7月前
|
SQL 存储 网络安全
关系数据库SQLserver 安装 SQL Server
【7月更文挑战第26天】
97 6
|
6月前
|
SQL 存储 数据库
SQL Server 中的备份类型详解
【8月更文挑战第31天】
160 0

热门文章

最新文章