MS SQL рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП "рд░рд┐рдпрд▓" рд╢рдмреНрдж


рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, MSSQL рдПрдиреНрдпреВрдорд░реЗрд╢рди рдмрдирд╛рдиреЗ / рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ , рдЬреЛ рдЕрдХреНрд╕рд░ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд, рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп, рдмрджрд╕реВрд░рдд, рдЬрдЯрд┐рд▓ рд░реВрдк рд╕реЗ рд╕рдорд░реНрдерд┐рдд рдХреЛрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдпрд╣ рддрд░реНрдХ рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдПрдХ рд╕рдВрдмрдВрдзрдкрд░рдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕реНрдерд╛рди рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрдерд╛рдирд╛рдиреНрддрд░рдг рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореЗрд░реЗ (рдФрд░ рдХреЗрд╡рд▓ рдореЗрд░реЗ) рдЕрднреНрдпрд╛рд╕ рдореЗрдВ рдХрдИ рдмрд╛рд░, рдпреЗ рд░реЗрдЦрд╛рдПрдБ рдкреИрджрд╛ рдирд╣реАрдВ рд╣реБрдИрдВ:
select * from Process where ProcessType = 1 /* Suspended */ 

рдпрд╛
 declare @processSuspended int = 1; select * from Process where ProcessType = @processSuspended; ------------------------------------------------------------------------------------------------------------ DECLARE @processSuspended INT; SELECT @processSuspended = Value FROM ProcessEnum WHERE Name = 'Suspended'; SELECT * FROM Process WHERE ProcessType = @processSuspended; ------------------------------------------------------------------------------------------------------------ CREATE FUNCTION ProcessEnum_Suspended() RETURNS INT AS BEGIN RETURN 1; END; SELECT * FROM Process WHERE ProcessType = ProcessEnum_Suspended(); 


рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдХрдард┐рдирд╛рдИ рд╕реНрддрд░реЛрдВ рдХреА рд╕рдорд╛рди рдмреИрд╕рд╛рдЦреАред
рдФрд░ рдореИрдВ рдЪрд╛рд╣рддрд╛ рд╣реВрдБ -
 SELECT * FROM Process WHERE ProcessType = EnumProcess.Suspended; 


рд╕рдорд╛рдзрд╛рди, рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ - рд╣рдо рд╕реАрдПрд▓рдЖрд░ рдкреНрд░рдХрд╛рд░ рдмрдирд╛рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдХреМрди рд▓рд┐рдЦрдирд╛, рдЕрд╕реЗрдВрдмрд▓реА рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдирд╛ рдФрд░ рд╣рд░ рд╕рдордп рдЙрдирдХреА рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХрддрд╛ рдХрд╛ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ?

рдЗрд╕ рд▓реЗрдЦ рдХреЗ рдЙрджреНрджреЗрд╢реНрдп


рдбрд┐рд╕реНрдХреНрд▓реЗрдорд░ : рдереЛрдбрд╝реЗ рд╕рдордп рдореЗрдВ рд╡рд┐рдЬрд╝реБрдЕрд▓ рд╕реНрдЯреВрдбрд┐рдпреЛ 2012, рдПрдордПрд╕ SQL тАЛтАЛрд╕рд░реНрд╡рд░ 2012 SP1, .Net рдлреНрд░реЗрдорд╡рд░реНрдХ 3.5 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрдЧреЗ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ рдХрд┐ рдХреИрд╕реЗред

рдЖрдЗрдП рдЗрд╕реЗ рдмрд┐рдирд╛ рд╢рдмреНрдж рдХреЗ рдЖрдЬрдорд╛рддреЗ рд╣реИрдВ


(UPD: рд╕рднреА рдПрдХ рд╕рд╛рде рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ )

1. рдЕрд╕реЗрдВрдмрд▓реА рдХреЛ рдЖрдпрд╛рдд рдХрд░реЗрдВ (рд▓реЗрдЦ рдХреЗ рдЕрдВрдд рдореЗрдВ - рд╕реНрд░реЛрдд рдХреЛрдб рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХ), (рдпрд╛рдж рд░рдЦреЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рдкрдврд╝реЗ)ред
ASSEMBLY SQLAutoEnums рдмрдирд╛рдПрдБ ...
 CREATE ASSEMBLY [SQLAutoEnums] FROM WITH PERMISSION_SET = UNSAFE GO CREATE FUNCTION [dbo].[SqlAutoEnums.EnumMembers_Current](@enumName [nvarchar](4000)) RETURNS TABLE ( [ID] [int] NULL, [Name] [nvarchar](4000) NULL ) WITH EXECUTE AS N'dbo' AS EXTERNAL NAME [SQLAutoEnums].[UserDefinedFunctions].[EnumMembersCurrent] GO CREATE FUNCTION [dbo].[SqlAutoEnumsCompile](@code [nvarchar](max)) RETURNS [varbinary](max) WITH EXECUTE AS CALLER AS EXTERNAL NAME [SQLAutoEnums].[UserDefinedFunctions].[SqlAutoEnumsCompile] GO CREATE FUNCTION [dbo].[SqlAutoEnumsGenerate](@tableName [nvarchar](4000), @columnPrefix [nvarchar](4000), @columnName [nvarchar](4000), @columnMember [nvarchar](4000), @columnValue [nvarchar](4000)) RETURNS [nvarchar](max) WITH EXECUTE AS CALLER AS EXTERNAL NAME [SQLAutoEnums].[UserDefinedFunctions].[SqlAutoEnumsGenerate] GO CREATE FUNCTION [dbo].[SqlAutoEnumsTryCompile](@code [nvarchar](max)) RETURNS [nvarchar](max) WITH EXECUTE AS CALLER AS EXTERNAL NAME [SQLAutoEnums].[UserDefinedFunctions].[SqlAutoEnumsTryCompile] GO 



2. рд╣рдо рдПрдХ рдкрд░реАрдХреНрд╖рдг рддрд╛рд▓рд┐рдХрд╛ SqlAutoEnums.Data рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЧрдгрдирд╛рдУрдВ рдХрд╛ рд╡рд┐рд╡рд░рдг рдФрд░ рдЗрд╕реЗ рджреЗрдЦрдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ рджреГрд╢реНрдп рд╣реЛрдЧрд╛ (рдмрд╛рдж рдореЗрдВ, рдЖрдк рдЗрд╕реЗ рдХрд┐рд╕реА рдЕрдиреНрдп рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдмрдирд╛рдП рд░рдЦрддреЗ рд╣реБрдП рдЧрдгрдирд╛ рдХреА рдЬрд╛рддреА рд╣реИ, рдлрд┐рд░ SqlAutoEnums.Data рддрд╛рд▓рд┐рдХрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ):
рдмрдирд╛рдПрдБ рддрд╛рд▓рд┐рдХрд╛ dboред [SqlAutoEnums.Data] ...
 CREATE TABLE [dbo].[SqlAutoEnums.Data]( [ID] [int] IDENTITY(1,1) NOT NULL, [Prefix] [nvarchar](50) NOT NULL, [Name] [nvarchar](50) NOT NULL, [MemberName] [nvarchar](50) NOT NULL, [MemberValue] [int] NOT NULL, CONSTRAINT [PK_SqlAutoEnums.Data] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO CREATE UNIQUE NONCLUSTERED INDEX [IX_SqlAutoEnums.Data] ON [dbo].[SqlAutoEnums.Data] ( [Prefix] ASC, [Name] ASC, [MemberName] ASC, [MemberValue] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO CREATE UNIQUE NONCLUSTERED INDEX [IX_SqlAutoEnums.Data.A] ON [dbo].[SqlAutoEnums.Data] ( [Name] ASC, [MemberValue] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO CREATE VIEW [dbo].[SqlAutoEnums.Data.View] AS SELECT ID , Prefix , Name , MemberName , MemberValue FROM dbo.[SqlAutoEnums.Data] 


3. рдЙрдкрдпреЛрдЧрд┐рддрд╛рд╡рд╛рджреА рдФрд░ рд╕рд╣рд╛рдпрдХ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛:
рдирд┐рд░реНрдорд╛рдг рдХрд╛рд░реНрдп ...
 CREATE FUNCTION [dbo].[SqlAutoEnums.Enum_Equals] ( @enumName NVARCHAR(100) ) RETURNS bit AS BEGIN DECLARE @res BIT = 0; SET @res = CASE WHEN EXISTS ( SELECT Name AS MemberName, ID AS MemberValue FROM dbo.[SqlAutoEnums.EnumMembers_Current](@enumName) except select MemberName, MemberValue FROM dbo.[SqlAutoEnums.EnumMembers_New](@enumName) ) OR EXISTS ( SELECT MemberName, MemberValue FROM dbo.[SqlAutoEnums.EnumMembers_New](@enumName) EXCEPT SELECT Name AS MemberName, ID AS MemberValue FROM dbo.[SqlAutoEnums.EnumMembers_Current](@enumName) ) THEN 0 ELSE 1 END; RETURN @res; END GO --================================================================================================================= CREATE FUNCTION [dbo].[SqlAutoEnums.Enum_HasDependencies] ( @schemaName NVARCHAR(100), @typeName NVARCHAR(100), @onColumns BIT, @oncomputedColumns BIT, @onParameters BIT, @onCheckConstraints BIT, @onCode BIT ) RETURNS bit AS BEGIN DECLARE @res BIT = 0; DECLARE @typeidname NVARCHAR(255) = '[' + @schemaName + '].[' + @typeName + ']'; IF (@onColumns = 1) BEGIN SET @res = CASE WHEN EXISTS ( SELECT 1 --OBJECT_NAME(object_id) AS object_name ,c.name AS column_name ,SCHEMA_NAME(t.schema_id) AS schema_name,TYPE_NAME(c.user_type_id) AS user_type_name,c.max_length,c.precision,c.scale,c.is_nullable,c.is_computed FROM sys.columns AS c INNER JOIN sys.types AS t ON c.user_type_id = t.user_type_id WHERE c.user_type_id = TYPE_ID(@typeidname) ) THEN 1 END; IF (1 = @res) RETURN @res; END; IF (@oncomputedColumns = 1) BEGIN SET @res = CASE WHEN EXISTS ( SELECT 1 --OBJECT_NAME(object_id) AS OBJECT_NAME ,COL_NAME(object_id, column_id) AS column_name FROM sys.sql_dependencies WHERE referenced_major_id = TYPE_ID(@typeidname) AND class = 2 AND -- schema-bound references to type OBJECTPROPERTY(object_id, 'IsTable') = 1 ) THEN 1 END; IF (1 = @res) RETURN @res; END; IF (@onParameters = 1) BEGIN SET @res = CASE WHEN EXISTS ( SELECT 1 -- OBJECT_NAME(object_id) AS object_name ,NULL AS procedure_number ,name AS param_name ,parameter_id AS param_num ,TYPE_NAME(p.user_TYPE_ID) AS type_name FROM sys.parameters AS p WHERE p.user_TYPE_ID = TYPE_ID(@typeidname) UNION SELECT 1 -- OBJECT_NAME(object_id) AS object_name ,procedure_number ,name AS param_name ,parameter_id AS param_num ,TYPE_NAME(p.user_TYPE_ID) AS type_name FROM sys.numbered_procedure_parameters AS p WHERE p.user_TYPE_ID = TYPE_ID(@typeidname) ) THEN 1 END; IF (1 = @res) RETURN @res; END; IF (@onCheckConstraints = 1) BEGIN SET @res = CASE WHEN EXISTS ( SELECT 1 -- SCHEMA_NAME(o.schema_id) AS schema_name ,OBJECT_NAME(o.parent_object_id) AS table_name ,OBJECT_NAME(o.object_id) AS constraint_name FROM sys.sql_dependencies AS d JOIN sys.objects AS o ON o.object_id = d.object_id WHERE referenced_major_id = TYPE_ID(@typeidname) AND class = 2 AND -- schema-bound references to type OBJECTPROPERTY(o.object_id, 'IsCheckCnst') = 1 -- exclude non-CHECK dependencies ) THEN 1 END; IF (1 = @res) RETURN @res; END; IF (@onCode = 1) BEGIN SET @res = CASE WHEN EXISTS ( SELECT 1 -- SCHEMA_NAME(o.schema_id) AS dependent_object_schema ,OBJECT_NAME(o.object_id) AS dependent_object_name ,o.type_desc AS dependent_object_type ,d.class_desc AS kind_of_dependency ,TYPE_NAME (d.referenced_major_id) AS type_name FROM sys.sql_dependencies AS d JOIN sys.objects AS o ON d.object_id = o.object_id AND o.type IN ('FN','IF','TF', 'V', 'P') WHERE d.class = 2 AND -- dependencies on types d.referenced_major_id = TYPE_ID(@typeidname) ) THEN 1 END; IF (1 = @res) RETURN @res; END; RETURN 0; END GO --================================================================================================================= CREATE FUNCTION [dbo].[SqlAutoEnums.EnumMembers_New] ( @enumName NVARCHAR(100) ) RETURNS TABLE AS RETURN ( -- select * from [SqlAutoEnums.NewEnumVals]() SELECT Prefix+Name AS EnumName, MemberName AS MemberName, MemberValue AS MemberValue FROM dbo.[SqlAutoEnums.Data.View] WHERE Prefix+Name = @enumName ) GO --================================================================================================================= CREATE FUNCTION [dbo].[SqlAutoEnums.Enums_Current]() RETURNS TABLE AS RETURN ( SELECT atold.assembly_id AS AssemblyId, asm.name AS AssemblyName, atold.user_type_id AS EnumId, atold.name AS EnumName FROM sys.assembly_types atold INNER JOIN sys.assemblies asm on asm.name LIKE 'SQLAutoEnums.Generated%' AND atold.assembly_id = asm.assembly_id ) GO --====================================================================================================================== CREATE FUNCTION [dbo].[SqlAutoEnums.Enums_New]() RETURNS TABLE AS RETURN ( SELECT DISTINCT Prefix+Name AS EnumName FROM dbo.[SqlAutoEnums.Data.View] ) GO --================================================================================================================= CREATE FUNCTION [dbo].[SqlAutoEnums.EnumsMembers_Current] ( ) RETURNS TABLE AS RETURN ( SELECT e.AssemblyId, e.AssemblyName, e.EnumId, e.EnumName, v.Name AS MemberName, v.ID AS MemberValue FROM ( SELECT AssemblyId, AssemblyName, EnumId, CAST(EnumName AS NVARCHAR(100)) AS EnumName FROM dbo.[SqlAutoEnums.Enums_Current]() ) e CROSS APPLY dbo.[SqlAutoEnums.EnumMembers_Current](e.EnumName) AS v ) GO --================================================================================================================= CREATE FUNCTION [dbo].[SqlAutoEnums.EnumsMembers_New] ( ) RETURNS TABLE AS RETURN ( SELECT Prefix+Name AS EnumName, MemberName AS MemberName, MemberValue AS MemberValue FROM dbo.[SqlAutoEnums.Data.View] ) GO 


4. рд╣рдо рд╕реНрдерд╛рдирд╛рдВрддрд░рдг рдмрдирд╛рдиреЗ / рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рддреЗ рд╣реИрдВ
рд░рдЪрдирд╛рддреНрдордХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ dbo [SqlAutoEnums.Renew] ...
 CREATE PROCEDURE [dbo].[SqlAutoEnums.Renew] WITH EXECUTE AS SELF AS BEGIN DECLARE @msg NVARCHAR(MAX); BEGIN TRY BEGIN TRAN --============================================================================================================ -- dropping current enums PRINT 'Current enums: clearing...'; IF (EXISTS ( SELECT 1 FROM dbo.[SqlAutoEnums.Enums_Current]() ec WHERE dbo.[SqlAutoEnums.Enum_Equals](ec.EnumName) = 0 AND dbo.[SqlAutoEnums.Enum_HasDependencies]('', ec.EnumName, 1, 1, 1, 1, 1) = 1 )) BEGIN SET @msg = 'Cannot modify or drop enums cause of dependencies: '; SELECT @msg += ec.EnumName + ', ' FROM dbo.[SqlAutoEnums.Enums_Current]() ec WHERE dbo.[SqlAutoEnums.Enum_Equals](ec.EnumName) = 0 AND dbo.[SqlAutoEnums.Enum_HasDependencies]('', ec.EnumName, 1, 1, 1, 1, 1) = 1 SET @msg = SUBSTRING(@msg, 1, LEN(@msg)-2); RAISERROR(@msg, 16, 2); END; --assembly list to drop DECLARE @asstodrop TABLE (Name NVARCHAR(MAX)); INSERT INTO @asstodrop (Name) SELECT ec.AssemblyName FROM dbo.[SqlAutoEnums.Enums_Current]() ec GROUP BY ec.AssemblyName HAVING SUM(CAST(dbo.[SqlAutoEnums.Enum_HasDependencies]('', ec.EnumName, 1, 1, 1, 1, 1) AS INT)) = 0 -- dropping enums DECLARE @qryDropEnum NVARCHAR(MAX); DECLARE @qryDropEnumToList NVARCHAR(MAX); DECLARE @oldEnumName NVARCHAR(MAX); DECLARE enumCursor CURSOR FOR SELECT ec.EnumName FROM dbo.[SqlAutoEnums.Enums_Current]() ec WHERE dbo.[SqlAutoEnums.Enum_HasDependencies]('', ec.EnumName, 1, 1, 1, 1, 1) = 0 OPEN enumCursor; FETCH NEXT FROM enumCursor INTO @oldEnumName; WHILE @@FETCH_STATUS = 0 BEGIN PRINT ' Dropping enum ' + @oldEnumName; SET @qryDropEnum = 'DROP TYPE [dbo].[' + @oldEnumName + ']'; SET @qryDropEnumToList = 'DROP FUNCTION [dbo].[' + @oldEnumName + '.ToList]'; IF (EXISTS (SELECT 1 FROM Information_schema.Routines WHERE SPECIFIC_SCHEMA = 'dbo' AND SPECIFIC_NAME = @oldEnumName + '.ToList')) EXEC sp_executesql @qryDropEnumToList; EXEC sp_executesql @qryDropEnum; FETCH NEXT FROM enumCursor INTO @oldEnumName; END; CLOSE enumCursor; DEALLOCATE enumCursor; -- dropping assemblies DECLARE @qryDropAss NVARCHAR(MAX); DECLARE @oldAssName NVARCHAR(MAX); DECLARE assCursor CURSOR FOR SELECT Name FROM @asstodrop; OPEN assCursor; FETCH NEXT FROM assCursor INTO @oldAssName; WHILE @@FETCH_STATUS = 0 BEGIN PRINT ' Dropping assembly ' + @oldAssName; SET @qryDropAss = 'DROP ASSEMBLY [' + @oldAssName + ']' EXEC sp_executesql @qryDropAss; FETCH NEXT FROM assCursor INTO @oldAssName; END; CLOSE assCursor; DEALLOCATE assCursor; PRINT 'Current enums: clear.'; --============================================================================================================ -- creating new assembly PRINT 'New assembly: generating...'; DECLARE @newAsmName NVARCHAR(255) = 'SQLAutoEnums.Generated.' + CAST(NEWID() AS NVARCHAR(100)); DECLARE @newAsmId BIGINT; PRINT ' Generated assembly name = ' + @newAsmName; DECLARE @code NVARCHAR(MAX) = dbo.SqlAutoEnumsGenerate('[SqlAutoEnums.Data.View]', 'Prefix', 'Name', 'MemberName', 'MemberValue'); DECLARE @compilemsg NVARCHAR(MAX) = dbo.SqlAutoEnumsTryCompile(@code); DECLARE @bin VARBINARY(MAX) = dbo.SqlAutoEnumsCompile(@code); IF (@bin IS NULL) BEGIN SET @msg = 'Cannot compile generated code:' + @compilemsg; RAISERROR(@msg, 16, 2); END; DECLARE @qryCreateAssembly NVARCHAR(MAX) = 'CREATE ASSEMBLY [' + @newAsmName + '] FROM ' + master.dbo.fn_varbintohexstr(@bin) + ' WITH PERMISSION_SET = SAFE;'; EXEC sp_executesql @qryCreateAssembly; SELECT @newAsmId = asm.assembly_id FROM sys.assemblies asm WHERE asm.name = @newAsmName; PRINT 'New assembly: done.'; --=========================================================================================================== -- registering new enums PRINT 'New enums: registering...' DECLARE @qryCreateEnum NVARCHAR(MAX); DECLARE @qryCreateEnumToList NVARCHAR(MAX); DECLARE @newEnumName NVARCHAR(MAX); DECLARE newEnumCursor CURSOR FOR SELECT EnumName FROM dbo.[SqlAutoEnums.Enums_New]() en WHERE en.EnumName NOT IN (SELECT EnumName FROM dbo.[SqlAutoEnums.Enums_Current]()); OPEN newEnumCursor; FETCH NEXT FROM newEnumCursor INTO @newEnumName; WHILE @@FETCH_STATUS = 0 BEGIN PRINT ' Registering enum ' + @newEnumName; SET @qryCreateEnum = 'CREATE TYPE [dbo].[' + @newEnumName + '] EXTERNAL NAME [' + @newAsmName + '].[SqlAutoEnumsGenerated.' + @newEnumName + ']'; EXEC sp_executesql @qryCreateEnum; SET @qryCreateEnumToList = 'CREATE FUNCTION [' + @newEnumName + '.ToList]() RETURNS TABLE (ID INT, Name NVARCHAR(4000)) EXTERNAL NAME [' + @newAsmName + '].[SqlAutoEnumsGenerated.' + @newEnumName + '].ToList;'; EXEC sp_executesql @qryCreateEnumToList; FETCH NEXT FROM newEnumCursor INTO @newEnumName; END; CLOSE newEnumCursor; DEALLOCATE newEnumCursor; PRINT 'New enums: done.' COMMIT TRANSACTION; END TRY BEGIN CATCH IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION; THROW; END CATCH; END GO 


4. рд╣рдо рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рдг рдХреЛ рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЗрдЬ рдкрд░ рдПрдХ рдЯреНрд░рд┐рдЧрд░ рд▓рдЯрдХрд╛рддреЗ рд╣реИрдВ
рдирд┐рд░реНрдорд╛рддрд╛ TRIGGER dboред [SqlAutoEnums.Renew.Trigger] ...
 CREATE TRIGGER dbo.[SqlAutoEnums.Renew.Trigger] ON [dbo].[SqlAutoEnums.Data] AFTER INSERT, DELETE, UPDATE AS BEGIN EXEC dbo.[SqlAutoEnums.Renew]; END 


рдЕрдм рдЗрд╕рдХрд╛ рдХреНрдпрд╛ рдХрд░реЗрдВ?



рд╣рдо рдкрд░реАрдХреНрд╖рдг рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╣реИрдВ

INSERT INTO dboред [SqlAutoEnums.Data] ...
 INSERT INTO dbo.[SqlAutoEnums.Data] (Prefix, Name, MemberName, MemberValue) VALUES ('Enum', 'Lolly', 'C', 14 ), ('Enum', 'Lolly', 'A', 1 ), ('Enum', 'Lolly', 'B', 2 ), ('Enum', 'Process', 'Running', 1 ), ('Enum', 'Process', 'Suspended', 2 ), ('Enum', 'Process', 'Terminated', 3 ) 


рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреНрдпрд╛ рд╣реИ:
 --  SELECT * FROM [SqlAutoEnums.Enums_Current]() --    SELECT * FROM [SqlAutoEnums.EnumsMembers_Current]() --   EnumProcess SELECT * FROM [EnumProcess.ToList]() --  DECLARE @processState EnumProcess; SET @processState = EnumProcess::Running; PRINT @processState.ToString(); --   DECLARE @process TABLE (ID INT, Comment NVARCHAR(100), ProcessState EnumProcess); INSERT INTO @process (ID, Comment, ProcessState) VALUES (0, ' : EnumProcess::Suspended', EnumProcess::Suspended), (0, ' : "Running" ', EnumProcess::Parse('Running')), (0, ' : 3', EnumProcess::Parse(3)) -- where SELECT ID, Comment, ProcessState, ProcessState.ToInt(), ProcessState.ToString() FROM @process WHERE ProcessState = EnumProcess::Suspended OR ProcessState = @processState; -- group SELECT ProcessState, ProcessState.ToInt(), ProcessState.ToString(), COUNT(*) AS [Count] FROM @process GROUP BY ProcessState; 


рдЗрдирд╕рд╛рдЗрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рд╕рд╛



SqlAutoEnums рдЕрд╕реЗрдВрдмрд▓реА рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, SqlAutoEnums .Generated рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдФрд░ рдкрдВрдЬреАрдХрд░рдг рд╣реИред * рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдбреЗрдЯрд╛ рд╕реЗ рдЕрд╕реЗрдВрдмрд▓рд┐рдпреЛрдВ, рдЬрд┐рд╕рдореЗрдВ рдЧрдгрдирд╛ рд╕реНрдерд┐рдд рд╣реИрдВред CLR рд╣реЛрд╕реНрдЯреЗрдб рдПрдирд╡рд╛рдпрд░рдореЗрдВрдЯ ( tynt , tynt ) рдХреА рд╕реАрдорд╛рдУрдВ рдХреЗ рдХрд╛рд░рдг, рдпрд╣ рдЕрдирд╛рдбрд╝реА, рд╕реНрдЯреНрд░рд┐рдВрдЧ.рдлреЙрд░реНрдо рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдХреВрджрддрд╛ рд╣реИ, рдЗрд╕реЗ csc.exe рдкрде рдкрде рдХреЗ рд╕рд╛рде рдХреЙрд▓ рдХрд░рдХреЗ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддрд╛ рд╣реИред \\ csc.exe "(рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛ рд░рд╣реЗ .NET рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП .NET 3.5 рдЗрдВрд╕реНрдЯреЙрд▓реЗрд╢рди рдкрде рд╕рд░реНрд╡рд░ рдкрд░ рд╕реНрдерд╛рдкрд┐рдд рд╣реИ ред рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рд╡рд╣рд╛рдБ рддрдХ рдкрд╣реБрдБрдЪ рд╣реИред рдкрд░реНрдпрд╛рд╡рд░рдгред рдкрд░реНрдпрд╛рд╡рд░рдгрдкрд░рд┐рд╡рд░реНрддрди (" TEMP ")ред рдПрдХ рджрд┐рди рд╣рдо рдХреБрдЫ рдХрдо рдЕрдирд╛рдбрд╝реА рдХреА рдЬрдЧрд╣ рд▓реЗрдВрдЧреЗред

рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдХрд┐ SQLServer рдирд╣реАрдВ рдЬрд╛рдирддрд╛ рд╣реИ рдФрд░ рдПрдирдо рдХреЛ рдирд╣реАрдВ рд╕рдордЭрддрд╛ рд╣реИ, рдПрдиреНрдпреВрдорд░реЗрд╢рди рдХреЗ рдирд╛рдо рд╕реЗ рдЦреЗрддреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдВрд░рдЪрдирд╛рдПрдВ рдирд┐рдореНрди рд╣реИрдВ:

 public enum FooEnum{A = 1, B = 2} public struct MyFooEnum { public MyFooEnum(FooEnum value) { _value = value; } public static MyFooEnum A { get { return new MyFooEnum(FooEnum.A);} } public static MyFooEnum B { get { return new MyFooEnum(FooEnum.B);} } private FooEnum _value; } 

рдЕрднреА рднреА рдмрд╣реБрдд рд╕рд╛рд░реЗ рддрдХрдиреАрдХреА рдЖрд╡рд░рдг рд╣реИрдВ (рдЖрдк CLR рдкреНрд░рдХрд╛рд░ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣рд╛рдБ , MSDN, Google ...

рдпрд╣ рдпрд╛рдж рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдЬреИрд╕реЗ рд╣реА рдЖрдк рдЕрдкрдиреЗ рдХрд╛рдо рдореЗрдВ рдЧрдгрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ (рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдлрд╝реАрд▓реНрдб рдФрд░ рдкрд░рд┐рдХрд▓рд┐рдд рдлрд╝реАрд▓реНрдб, рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ / рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдЖрджрд┐), рдлрд┐рд░, рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХреА рддрд░рд╣, рдкрд░рд┐рд╡рд░реНрддрди (ALTER TYPE - DROP рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рдХрд╛рд░рдг) рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред , рдлрд┐рд░ рдмрдирд╛рдПрдБ) рдпрд╛ рд╣рдЯрд╛рдпрд╛ рдирд╣реАрдВ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕рднреА рд▓рд┐рдВрдХ рд╣рдЯрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрджрд┐ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЗрд╡рд▓ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ / рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдХреЛрдб рдХреЗ рдЕрдВрджрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдкреНрд░рдХреНрд░рд┐рдпрд╛ / рдХрд╛рд░реНрдп рдПрдХ рдЕрдкрд╡рд╛рдж рдпрд╛ рдЗрд╕рдХреЗ рднрд╛рдЧ рдирд╣реАрдВ рд╣реЛрдиреЗ рдкрд░ рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рде рдмрд╛рд╣рд░ рдЧрд┐рд░ рд╕рдХрддрд╛ рд╣реИред
рдЗрд╕рд▓рд┐рдП, рдПрдХ рдирдИ рдЕрд╕реЗрдВрдмрд▓реА рдмрдирд╛рддреЗ рд╕рдордп, рд╕рднреА рдПрдиреБрдорд░реЗрд╢рдиреНрд╕ рдЬрд┐рдирдХреЗ рдкрд╛рд╕ рдирд┐рд░реНрднрд░рддрд╛рдПрдБ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, "рдкреБрд░рд╛рдиреЗ" рдЕрд╕реЗрдВрдмрд▓реА рдореЗрдВ, рдРрд╕реЗ рдПрдиреБрдорд░реЗрд╢рдиреНрд╕ рдмрдиреЗ рд░рд╣рддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ рдФрд░ рдЬрд┐рдирдХреА рдирд┐рд░реНрднрд░рддрд╛рдПрдБ рд╣реЛрддреА рд╣реИрдВред

SqlAutoEnums.dll рдХреЗ рд▓рд┐рдП рд╡рд╛рджрд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╡рд┐рдзрд╛рдирд╕рднрд╛ рд╕реНрд░реЛрдд

рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдХреЛ рдКрдкрд░ рд╕реЗ рд▓рд╛рдн рд╣реЛрдЧрд╛ рдпрд╛ рдЕрдзрд┐рдХ рдЙрдиреНрдирдд рд╡рд┐рдХрд▓реНрдк рдХреЗ рд╕рд╛рде рдЖрдПрдЧрд╛ред

Source: https://habr.com/ru/post/In187966/


All Articles