Asy*_*ous 30 sql t-sql sql-server
嗨,谢谢你读这篇文章.
我试图使用IF EXISTS/IF NOT EXISTS语句来检查对象是否存在.基本上我想跳过它,如果它在那里或创建它,如果它不存在.
我用两种不同的方式编写代码,但是我收到一个错误:创建函数必须是批处理中唯一的函数.如果我把GO放在下面的插图语句之间,我会收到另一个警告:GO附近的语法不正确.
我在哪里错了?
IF NOT EXISTS
(select * from Information_schema.Routines where SPECIFIC_SCHEMA='dbo'
AND SPECIFIC_NAME = 'FMT_PHONE_NBR' AND Routine_Type='FUNCTION')
/*CREATE FUNCTION TO FORMAT PHONE NUMBERS*/
CREATE FUNCTION [dbo].[FMT_PHONE_NBR](@phoneNumber VARCHAR(12))
RETURNS VARCHAR(12)
AS
BEGIN
RETURN SUBSTRING(@phoneNumber, 1, 3) + '-' +
SUBSTRING(@phoneNumber, 4, 3) + '-' +
SUBSTRING(@phoneNumber, 7, 4)
END
GO
Run Code Online (Sandbox Code Playgroud)
或这个:
IF NOT EXISTS
(SELECT name FROM sys.objects WHERE name = 'dbo.FMT_PHONE_NBR')
GO
/*CREATE FUNCTION TO FORMAT PHONE NUMBERS*/
CREATE FUNCTION [dbo].[FMT_PHONE_NBR](@phoneNumber VARCHAR(12))
RETURNS VARCHAR(12)
AS
BEGIN
RETURN SUBSTRING(@phoneNumber, 1, 3) + '-' +
SUBSTRING(@phoneNumber, 4, 3) + '-' +
SUBSTRING(@phoneNumber, 7, 4)
END
GO
Run Code Online (Sandbox Code Playgroud)
感谢您查看此内容!
Tre*_*eyE 40
解决此问题的最简单方法是删除已存在的函数,然后重新创建它:
/* If we already exist, get rid of us, and fix our spelling */
IF OBJECT_ID('dbo.FMT_PHONE_NBR') IS NOT NULL
DROP FUNCTION FMT_PHONE_NBR
GO
/*CREATE FUNCTION TO FORMAT PHONE NUMBERS*/
CREATE FUNCTION [dbo].[FMT_PHONE_NBR](@phoneNumber VARCHAR(12))
RETURNS VARCHAR(12)
AS
BEGIN
RETURN SUBSTRING(@phoneNumber, 1, 3) + '-' +
SUBSTRING(@phoneNumber, 4, 3) + '-' +
SUBSTRING(@phoneNumber, 7, 4)
END
GO
Run Code Online (Sandbox Code Playgroud)
请注意上面"object_id"函数的用法.这实际上是一种检查对象是否存在的常用方法,尽管它受到某些约束.
你可以在这里阅读更多相关信息:OBJECT_ID
Phi*_*ley 24
当我长时间在这堵砖墙上打我的头时,我会再扔两美分.
正如所指出的那样,只有在它不存在的情况下添加它才会很好,但是如果不使用动态SQL就不可能在T-SQL中添加...并且包装你的函数,过程,触发器,视图,甚至可能是更加模糊不清的物体,因为动态陈述太不切实际了.(不要让我支持连续可能包含4个以上单个撇号的源代码!)
删除(如果存在)和(重新)创建是可行的解决方案.据推测,如果您要推出新代码,您可能希望创建该对象(如果该对象尚未存在),否则将删除现有/旧代码并将其替换为新代码.(如果您可能不小心将"新"代码替换为"旧"代码,则会出现版本控制问题,这是一个不同且难度较大的主题.)
丢弃旧代码时,真正的问题是丢失信息.什么信息?我经常遇到的是访问权限:谁拥有EXECUTE或者对某些功能SELECT拥有对象权限?丢弃和更换,他们走了.当然,答案是将访问权限编写为部署脚本的一部分.但是,如果您遇到不同数据库托管环境具有不同配置(登录,域,组等)的情况,您可能会遇到以下情况:无法知道现有访问权限是什么在给定的实例上,如果您只是删除并重新创建它,现有用户可能无法再访问它.(扩展属性和esoterica的其他位同样会受到影响.)
对此的第一个也是最好的解决方案是实现强大的安全性.设置数据库角色,为角色分配/关联适当的权限,然后您不必知道角色中的谁 - 这将是环境管理员的工作.(你仍然需要GRANT EXECUTE on ThisProc to dbo.xxx在脚本的末尾有类似的东西,但这并不是那么难.
如果像我一样,你(a)没有被授权推出一个好的和强大的安全模型,并且(b)是懒惰的,并且可能不会检查数百行长存储过程文件的结尾访问权限代码,您可以执行以下操作.(这是为存储过程设置的,但适用于函数和其他对象.)
-- isProcedure
-- IsScalarFunction (Returns single value)
-- IsTableFunction (Declared return table structure, multiple statements)
-- IsInlineFunction (Based on single select statement)
-- IsView
IF objectproperty(object_id('dbo.xxx'), 'isProcedure') is null
BEGIN
-- Procedure (or function) does not exist, create a dummy placeholder
DECLARE @Placeholder varchar(100)
SET @Placeholder = 'CREATE PROCEDURE dbo.xxx AS RETURN 0'
EXEC(@PlaceHolder)
-- Configure access rights
GRANT EXECUTE on dbo.xxx TO StoredProcedureUser
END
GO
ALTER PROCEDURE dbo.xxx
(etc.)
GO
Run Code Online (Sandbox Code Playgroud)
这将:
ALTER并使用所需的代码进行设置.还存在在模式中管理基于代码的对象(主要是存储过程)的问题,其中模式可能不存在.我还没有想出那一个,如果你很幸运,你将永远不会陷入同样的怪异局面.
死灵法术。
删除不是一个好主意,因为可能在对象上设置了权限。
因此,正确的做法实际上是
A) 如果该函数不存在(虚拟),则创建该函数
B) 如果该函数已经存在,则更改该函数。(它可能不是最新的)
例子:
-- DROP FUNCTION IF EXISTS [dbo].[TestFunction]
-- Do not drop the function if it exists - there might be privileges granted on it...
-- You cannot alter function from table-valued function to scalar function or vice-versa
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TestFunction]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
BEGIN
-- CREATE FUNCTION dbo.[TestFunction]() RETURNS int AS BEGIN RETURN 123 END
-- CREATE FUNCTION dbo.[TestFunction]() RETURNS table AS RETURN (SELECT * FROM information_schema.tables)
EXECUTE('
CREATE FUNCTION dbo.[TestFunction]() RETURNS int AS BEGIN RETURN 123 END
')
END
GO
-- ALTER FUNCTION dbo.[TestFunction](@abc int) RETURNS table AS RETURN (SELECT * FROM information_schema.tables)
ALTER FUNCTION dbo.[TestFunction]() RETURNS int AS BEGIN RETURN 'test' END
Run Code Online (Sandbox Code Playgroud)
请注意,您不能将表值函数更改为标量函数,反之亦然。
但是,您可以随意更改参数类型和参数数量 - 以及返回模式。
| 归档时间: |
|
| 查看次数: |
32480 次 |
| 最近记录: |