mysql2012更改表名_SQL Server中修改“用户自定义表类型”问题的分析与方法

前言

SQL Server开发过程中,为了传入数据集类型的变量(比如接受C#中的DataTable类型变量),需要定义“用户自定义表类型”,通过“用户自定义表类型”可以接收二维数据集作为参数,在需要修改“用户自定义表类型”的时候,增加字段,删除字段,修改字段类型等,它没有像表一样的alter table语法来进行修改。

只能通过删除重建来实现,但是在删除“用户自定义表类型”的时候会提示有对象引用它(某些存储过程用到了这个“用户自定义表类型”),因此无法删除。

为了达到公用的目的,有时候一个TableType可以在多个地方分别被引用到,这样的话,势必要先删除所有的引用了这个“用户自定义表类型”的对象(存储过程等)

如果这个“用户自定义表类型”被多个存储过程引用,那么就要分别删除多个引用了“用户自定义表类型”的存储过程,然后修改“用户自定义表类型”,在重建存储过程,这样做起来似乎有点绕,这个问题可以用过EXEC sys.sp_refreshsqlmodule这个系统函数来简介实现“用户自定义表类型”的定义

TableType的基本使用

如下创建一个用户自定义表类型

90911f4df47d2389ded63d457246be58.png

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

38a66e4ff7b6ec3918f22bd21b347f79.png

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

4238f7b9a28990df9712feac0cf69262.png

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

64fa08ace6e8e58743598da3ec1d79d4.png

TableType的修改

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

d23d345623e5b135720e7303ab758a15.png

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

aaa0237c0bcbf59e1dbdcb32ed2ff491.png

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

4b763caa0db6a7c392d1356799aa3525.png

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

71c4f3a04af73018ad43f119a69de8c8.png

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

c0e071fb1a1a88c2b6d1b10dac37d9c1.png

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

f55b68dee2c81e8c47a5eadc1e6c02a3.png

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

fadec052e1afdf9b775cc27981df67cc.png

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

15e1536398bdde830c78be2ec99ef7a0.png

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

78fdaf7f70f953b7f1f0b57ddb100682.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。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值