设为首页 收藏本站
查看: 1680|回复: 0

[经验分享] 关于SQL Server中修改“用户自定义表类型”的问题

[复制链接]

尚未签到

发表于 2017-12-13 17:33:17 | 显示全部楼层 |阅读模式
  本文出处:http://www.cnblogs.com/wy123/p/7282682.html
  (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他)
  SQL Server开发过程中,为了传入数据集类型的变量(比如接受C#中的DataTable类型变量),需要定义“用户自定义表类型”,通过“用户自定义表类型”可以接收二维数据集作为参数,
  在需要修改“用户自定义表类型”的时候,增加字段,删除字段,修改字段类型等,它没有像表一样的alter table语法来进行修改。
  只能通过删除重建来实现,但是在删除“用户自定义表类型”的时候会提示有对象引用它(某些存储过程用到了这个“用户自定义表类型”),因此无法删除。
  为了达到公用的目的,有时候一个TableType可以在多个地方分别被引用到,这样的话,势必要先删除所有的引用了这个“用户自定义表类型”的对象(存储过程等)
  如果这个“用户自定义表类型”被多个存储过程引用,那么就要分别删除多个引用了“用户自定义表类型”的存储过程,然后修改“用户自定义表类型”,在重建存储过程,这样做起来似乎有点绕,
  这个问题可以用过EXEC sys.sp_refreshsqlmodule这个系统函数来简介实现“用户自定义表类型”的定义
  TableType的基本使用
  如下创建一个用户自定义表类型
DSC0000.png

  定义的TableType可以在用户自定义表类型中找到
DSC0001.png

  创建两个存储过程,分别用到了上面定义的用户自定义表类型,模拟用户自定义表类型被引用的情况
DSC0002.png

  此时的存储过程可以接收TableType参数并正常运行
DSC0003.png

  TableType的修改
  TableType类型不支持alter语法,也即无法直接修改TableType的定义
DSC0004.png

  那么只能通过删除TableType的方法来重建这个TableType,当删除的时候,仍然报错,提示“因为它正由对象 '***' 引用。可能还有其他对象在引用此类型。”
DSC0005.png

  此时只能删除引用了这个TableType的对象来解决,下面可以查到那些对象引用了某一个TableType,然后分别删除,重建TableType,再重建存储过程,有点绕弯子。
DSC0006.png

  可以先将自定义的某个TableType重命名,重命名的过程中有一个警告,这里先忽略它,随后可以直接Drop Type dbo.MyTableType
DSC0007.png

  删除原TableType之后,重建(重定义)TableType
DSC0008.png

  重建TableType之后,先前存储过程中用到这个TableType的存储过程是无法编译通过的
DSC0009.png

  此时就需要重新刷新引用对象的定义
DSC00010.png

  刷新完成之后,原存储过程就可以正常编译了
DSC00011.png

  最后删除原始的TableType被重命名的TableType(被第一步重名的那个)
DSC00012.png

  这样子,整个过程就无需因为修改TableType的定义而删除引用了TableType的对象了,在修改了TableType的定义之后,引用了这个TableType的对象可以正常运行,也可以根据修改之后的TableType做具体的使用
  完整的脚本如下
  

--判断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。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-423735-1-1.html 上篇帖子: SQL Server数据库基础笔记 下篇帖子: SQL Server 事务隔离级别详解
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表