Dans SQL Server 2005, existe-t-il le concept d'une fonction à usage unique ou d'une fonction locale déclarée à l'intérieur d'un script SQL ou d'une procédure stockée? J'aimerais rédiger un peu de complexité dans un script que j'écris, mais cela nécessiterait de pouvoir déclarer une fonction.
Juste curieux.
Tu peux appeler CREATE Function
près du début de votre script et DROP Function
Près de la fin.
Vous pouvez créer des procédures stockées temporaires telles que:
create procedure #mytemp as
begin
select getdate() into #mytemptable;
end
dans un script SQL, mais pas les fonctions. Vous pouvez aussi avoir le magasin proc qui en résulte dans une table temporaire, puis utiliser ces informations plus tard dans le script.
Common Table Expressions vous permettent de définir ce que sont essentiellement des vues qui ne durent que dans le cadre de vos instructions select, insert, update et delete. Selon ce que vous devez faire, ils peuvent être extrêmement utiles.
Je sais que je pourrais être critiqué pour avoir suggéré SQL dynamique, mais c'est parfois une bonne solution. Assurez-vous simplement de bien comprendre les implications en termes de sécurité avant d’envisager cela.
DECLARE @add_a_b_func nvarchar(4000) = N'SELECT @c = @a + @b;';
DECLARE @add_a_b_parm nvarchar(500) = N'@a int, @b int, @c int OUTPUT';
DECLARE @result int;
EXEC sp_executesql @add_a_b_func, @add_a_b_parm, 2, 3, @c = @result OUTPUT;
PRINT CONVERT(varchar, @result); -- prints '5'
Ce qui suit est ce que j’ai utilisé j’ai utilisé dans le passé pour répondre à la nécessité d’une FDU scalaire en MS SQL:
IF OBJECT_ID('tempdb..##fn_Divide') IS NOT NULL DROP PROCEDURE ##fn_Divide
GO
CREATE PROCEDURE ##fn_Divide (@Numerator Real, @Denominator Real) AS
BEGIN
SELECT Division =
CASE WHEN @Denominator != 0 AND @Denominator is NOT NULL AND @Numerator != 0 AND @Numerator is NOT NULL THEN
@Numerator / @Denominator
ELSE
0
END
RETURN
END
GO
Exec ##fn_Divide 6,4
Cette approche qui utilise une variable globale pour la procédure vous permet d’utiliser la fonction non seulement dans vos scripts, mais également dans vos besoins en SQL dynamique.
Dans les scripts, vous avez plus d'options et une meilleure idée de la décomposition rationnelle. Examinez le mode SQLCMD (Menu Requête -> mode SQLCMD), plus particulièrement les commandes: setvar et: r.
Dans une procédure stockée, vos options sont très limitées. Vous ne pouvez pas créer définir une fonction directement avec le corps d'une procédure. Le mieux que vous puissiez faire est quelque chose comme ceci, avec du SQL dynamique:
create proc DoStuff
as begin
declare @sql nvarchar(max)
/*
define function here, within a string
note the underscore prefix, a good convention for user-defined temporary objects
*/
set @sql = '
create function dbo._object_name_twopart (@object_id int)
returns nvarchar(517) as
begin
return
quotename(object_schema_name(@object_id))+N''.''+
quotename(object_name(@object_id))
end
'
/*
create the function by executing the string, with a conditional object drop upfront
*/
if object_id('dbo._object_name_twopart') is not null drop function _object_name_twopart
exec (@sql)
/*
use the function in a query
*/
select object_id, dbo._object_name_twopart(object_id)
from sys.objects
where type = 'U'
/*
clean up
*/
drop function _object_name_twopart
end
go
Ceci se rapproche d'une fonction temporaire globale, si une telle chose existait. Il est toujours visible par les autres utilisateurs. Vous pouvez ajouter le @@ SPID de votre connexion pour personnaliser le nom, mais le reste de la procédure nécessiterait également l'utilisation de SQL dynamique.