我有一个SQLCLR触发器。它内部包含一个大而凌乱的SELECT,其中包含:
(CASE WHEN EXISTS(SELECT * FROM INSERTED I WHERE I.ID = R.ID)
THEN '1' ELSE '0' END) AS IsUpdated -- Is selected row just added?
以及JOIN等。我希望将结果作为包含所有内容的单个表格。
问题1 。我可以将此SELECT移动到SQL Server端吗?如果是的话,怎么做?
说“移动”,我的意思是创建一个存储过程或其他可以在循环中读取数据集之前执行的过程。
只有当答案为“是”时,以下两个问题才有意义。
为什么我要移动SELECT?首先,我不喜欢将SQL与C#代码混合。第二,我认为服务器端查询运行得更快,因为服务器有更多机会缓存它们。
问题2 。我对吗?这是某种优化吗?
此外,SELECT包含常量字符串,但它们是可本地化的。例如,
WHERE R.Status = "Enabled"
“启用”应该更改为法语,德语等。所以,我想编写2个静态方法 - OnCreate和OnDestroy - 然后将它们标记为存储过程。在服务器端注册/取消注册我的程序集时,只需分别调用它们。在OnCreate格式中,SELECT字符串将{0},{1} ...替换为程序集资源中的必需值。然后我只能本地化资源,而不是每个脚本。
问题3 。这是好主意吗?在(un)注册程序集后,是否有一个现有的属性来标记SQL Server自动执行的方法?
此致
答案 0 :(得分:1)
那么,SQL-CLR触发器也会在服务器进程内执行服务器 - 所以这也是服务器端,没有任何好处。
但是我同意 - 触发器应该尽可能用T-SQL编写 - 在C#中使用触发器没有什么大的好处....你能显示整个触发器代码吗?除非它包含非常奇怪的球,否则转换为T-SQL应该很容易。
我没有看到你如何将SELECT“移动”到SQL端并将其余的代码保存在C#中 - 要么你的触发器在T-SQL中(我的偏好),要么它在C#/中SQL-CLR - 我认为没有任何方法可以“混合搭配”。
答案 1 :(得分:1)
首先,您可能不需要在正在执行的任何查询中执行该类型的子查询。 INSERTED表只有已更新的行(或插入但我们可以假设这是基于代码中的注释的UPDATE触发器)。所以你可以INNER JOIN,你只能匹配Table中的行和别名“R”,或者你可以LEFT JOIN,你可以告诉R中的哪些行已经更新,因为所有列的显示为NULL的行都没有更新。
问题1)正如下面的marc_s所述,触发器在数据库的上下文中执行。但它超越了这一点。所有与数据库相关的代码,包括SQLCLR在数据库中执行。这里没有客户端。这是大多数人使用SQLCLR的问题:它在SQL Server上下文中运行。关于想要从触发器调用存储过程:可以完成但是INSERTED和DELETED表只存在于触发器本身的上下文中。
问题2)看来这个问题应该以“还有SELECT”开头。这里有两件事需要考虑。首先,在测试“状态”值(或任何查找值)时,由于未向用户显示,因此应使用数值。 “启用”的“状态”应该类似于“1”,因此语言不相关。另一个好处是,不仅将状态值存储为数字占用的空间要少得多,而且它们的比较速度也要快得多。其次,要显示给用户的任何需要对语言差异敏感的文本应该在表中,以便您可以传入LanguageId或LocaleId以获取要显示的相应法语,德语等字符串。您可以在另一个表中设置用户或系统的LocaleId。
问题3)如果通过“注册”表示大会是创建或删除,那么您可以通过DDL触发器捕获这些事件。你可以在这里找一些基础知识:
http://msdn.microsoft.com/en-us/library/ms175941(v=SQL.90).aspx
但是CREATE ASSEMBLY和DROP ASSEMBLY是可以捕获的事件。
如果你在谈论从内存加载和卸载程序集时,我不知道如何捕获它。
答案 2 :(得分:0)
问题1。 http://www.sqlteam.com/article/stored-procedures-returning-data
问题3。 看起来没有合适的属性,至少在Microsoft.SqlServer.Server Namespace中。