SQL Server中修改“用户自定义表类型”问题的分析与方法
前言
SQL Server开发过程中,为了传入数据集类型的变量(比如接受C#中的DataTable类型变量),需要定义“用户自定义表类型”,通过“用户自定义表类型”可以接收二维数据集作为参数,在需要修改“用户自定义表类型”的时候,增加字段,删除字段,修改字段类型等,它没有像表一样的alter table语法来进行修改。
只能通过删除重建来实现,但是在删除“用户自定义表类型”的时候会提示有对象引用它(某些存储过程用到了这个“用户自定义表类型”),因此无法删除。
为了达到公用的目的,有时候一个TableType可以在多个地方分别被引用到,这样的话,势必要先删除所有的引用了这个“用户自定义表类型”的对象(存储过程等)
如果这个“用户自定义表类型”被多个存储过程引用,那么就要分别删除多个引用了“用户自定义表类型”的存储过程,然后修改“用户自定义表类型”,在重建存储过程,这样做起来似乎有点绕,这个问题可以用过EXEC sys.sp_refreshsqlmodule这个系统函数来简介实现“用户自定义表类型”的定义
TableType的基本使用
如下创建一个用户自定义表类型
定义的TableType可以在用户自定义表类型中找到
创建两个存储过程,分别用到了上面定义的用户自定义表类型,模拟用户自定义表类型被引用的情况
此时的存储过程可以接收TableType参数并正常运行
TableType的修改
TableType类型不支持alter语法,也即无法直接修改TableType的定义
那么只能通过删除TableType的方法来重建这个TableType,当删除的时候,仍然报错,提示“因为它正由对象 '***' 引用。可能还有其他对象在引用此类型。”
此时只能删除引用了这个TableType的对象来解决,下面可以查到那些对象引用了某一个TableType,然后分别删除,重建TableType,再重建存储过程,有点绕弯子。
可以先将自定义的某个TableType重命名,重命名的过程中有一个警告,这里先忽略它,随后可以直接Drop Type dbo.MyTableType
删除原TableType之后,重建(重定义)TableType
重建TableType之后,先前存储过程中用到这个TableType的存储过程是无法编译通过的
此时就需要重新刷新引用对象的定义
刷新完成之后,原存储过程就可以正常编译了
最后删除原始的TableType被重命名的TableType(被第一步重名的那个)
这样子,整个过程就无需因为修改TableType的定义而删除引用了TableType的对象了,在修改了TableType的定义之后,引用了这个TableType的对象可以正常运行,也可以根据修改之后的TableType做具体的使用
完整的脚本如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
--判断Type是否存在,如果存在,重命名,随后之后才再删除,否则无法直接删除 IF EXISTS ( SELECT 1 FROM sys.types t join sys.schemas s on t.schema_id=s.schema_id and t. name = 'MyTableType' and s. name = 'dbo' ) EXEC sys.sp_rename 'dbo.MyTableType' , 'obsoleting_MyTableType' ; GO --重建TYPE,比如原来是四个字段,现在想修改为三个字段,或者原来有三个字段想加一个字段变成四个字段 CREATE TYPE dbo.MyTableType AS TABLE ( Id INT NOT NULL , Name VARCHAR (255) NOT NULL , Remark VARCHAR (255) ) GO --将原来引用将要删除的TYPE全部重建一遍,否则原始存储过程会报错 DECLARE @ Name NVARCHAR(500); DECLARE REF_CURSOR CURSOR FOR SELECT referencing_schema_name + '.' + referencing_entity_name FROM sys.dm_sql_referencing_entities( 'dbo.MyTableType' , 'TYPE' ); OPEN REF_CURSOR; FETCH NEXT FROM REF_CURSOR INTO @ Name ; WHILE (@@FETCH_STATUS = 0) BEGIN EXEC sys.sp_refreshsqlmodule @ name = @ Name ; FETCH NEXT FROM REF_CURSOR INTO @ Name ; END ; CLOSE REF_CURSOR; DEALLOCATE REF_CURSOR; GO --最后删除原始的被重命名的TableType(被第一步重名的那个) IF EXISTS ( SELECT 1 FROM sys.types t join sys.schemas s on t.schema_id=s.schema_id and t. name = 'obsoleting_MyTableType' and s. name = 'dbo' ) DROP TYPE dbo.obsoleting_MyTableType GO --最后执行授权 GRANT EXECUTE ON TYPE::dbo.MyTableType TO public GO |
总结:
TableType可以方便地接受二维数据作为参数,从而可以达到批量处理数据的目的,避免传递进去一大堆字符串,然后在对字符串解析的做法,从而可以在一定程度上提高sql的运行效率。
不过TableType的修改确实存在一定的问题,直接修改TableType会存在级联删除数据库对象的情况,可以通过“曲线救国”的方式,来减小工作量的情况下修改TableType。
SQL Server中修改“用户自定义表类型”问题的分析与方法的更多相关文章
- MS SQL SERVER 中的系统表
MS SQL SERVER 中的系统表 序号 名称 说明 备注 1 syscolumns 每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行. 2 syscomments 包含每 ...
- Sql server中如何将表A和表B的数据合并(乘积方式)
sql server中如何将表A 和表B的数据合并成乘积方式,也就是说表A有2条数据,表B有3条数据,乘积后有6条数据, 这就要用到sql中的笛卡尔积方式了 1.什么是笛卡尔积 笛卡尔积在SQL中的实 ...
- SQL Server中查询用户的对象权限和角色的方法
--SQL Server中查询用户的对象权限和角色的方法 -- 查询用户的object权限 exec sp_helprotect NULL, 'sa' -- 查询用户拥有的role exec sp_h ...
- SQL SERVER中LIKE使用变量类型输出结果不同
前言:Sql Server中LIKE里面使用不同的变量类型导致查询结果不一致的问题,其实看似有点让人不解的现象背后实质跟数据类型的实现有关. 一.我们先来创建示例演示具体操作 CREATE TABLE ...
- SQL SERVER中查询某个表或某个索引是否存在
查询某个表是否存在: 在实际应用中可能需要删除某个表,在删除之前最好先判断一下此表是否存在,以防止返回错误信息.在SQL SERVER中可通过以下语句实现: IF OBJECT_ID(N'表名称', ...
- C# 如何获取SQL Server 中指定数据表的所有字段名和字段类型
如何获取指定数据表的所有字段名和字段类型.SqlConnection.GetSchema方法有2个重载形式,获取指定数据表的所有字段名和字段类型的秘密就在GetSchema (String, Stri ...
- 在 SQL Server 中查询EXCEL 表中的数据遇到的各种问题
SELECT * FROM OpenDataSource( 'Microsoft.Jet.OLEDB.4.0','Data Source="D:\KK.xls";User ID=A ...
- [转]SQL Server中临时表与表变量的区别
[转]http://blog.csdn.net/skyremember/archive/2009/03/05/3960687.aspx 我们在数据库中使用表的时候,经常会遇到两种使用表的方法,分别就是 ...
- 关于SQL Server中的系统表之一 sysobjects
微软Sql Server数据库是企业开发管理中最常用的数据库系统之一.其功能强大而且使用简单.方便.我们在数据库中创建数据库.表.视图.触发器.存储过程.函数等信息. 最常用的功能之一,查询数据,例如 ...
随机推荐
- sklearn之转换器和估计器
sklearn之转换器和估计器 转换器 估计器(sklearn机器学习算法的实现) 转换器 想一下之前做的特征工程的步骤? 实例化(实例化的是一个转换器类(Transformer)--特征工程的父类) ...
- 关于如何在MyEclipse下修改项目名包名,以及类
1.修改项目名,右键选择properties->web->web-Context-root修改名称或者直接按F2修改.2,修改包名,右键选择Refactor->rename修改名称即 ...
- nrf52810/52832开发板能跑,自己的PCB不能跑的原因
1.PCB图片对比 这是我的开发板原理图: 这是我画的PCB原理图: 发现其实开发板上就是比我的多了两个外部晶振. 例程代码一般都是用外部晶振作为时钟,所以用例程的代码跑不通我的PCB. 2.解决办法 ...
- Mybatis类型转换BUG
案例:mybatis框架的使用中是否遇到过前台传入数据后mybatis后台并不执行sql的情况呢? 比如:前台传入一个状态var flag //空字符,0,1 然后你用int接收,到mybatis框架 ...
- 提升 RTC 音频体验 - 从搞懂硬件开始
前言 RTC(实时音视频通信)技术的快速发展,助力了直播.短视频等互动娱乐形式的普及:在全球疫情持续蔓延的态势下,云会议需求呈现爆发式增长,进一步推动了 RTC 行业的快速发展.为了给客户提供稳定可靠 ...
- go定义接口以及类怎么使用接口
go定义接口以及类怎么使用接口 多态是指代码可以根据类型的具体实现采取不同行为的能力.如果一个类型实现了某个接口,所有使用这个接口的地方,都可以支持这种类型的值. 接口是用来定义行为的类型.这些被定义 ...
- mysql-select as
给查询对象起个别名. 把查询对像起个别名的作用. select ID as 用户ID,Name as 用户名 from Table_user
- Python函数之传参
目录 1. 函数传参 1.1 参数的作用 1.2 形参和实参 1.3 位置参数 1.4 关键字参数 1.5 默认实参 1.6 参数总结 2. 可变参数 1. 函数传参 1.1 参数的作用 1.2 形参 ...
- 52-Linked List Cycle
Linked List Cycle My Submissions QuestionEditorial Solution Total Accepted: 102785 Total Submissions ...
- MySQL 的查询优化
说起 MySQL 的查询优化,相信大家收藏了一堆奇技淫巧:不能使用 SELECT *.不使用 NULL 字段.合理创建索引.为字段选择合适的数据类型..... 你是否真的理解这些优化技巧?是否理解它背 ...