├── PostgreSQL ├── pgadmin3_support_10.sql ├── top 10 command for admin.sql └── account │ ├── check_account.sql │ └── README.md ├── SQL Server ├── !hotfix │ └── sql2017 after CU3.sql ├── buffer pool │ └── dmv buffer pool.sql ├── Service Broker │ ├── mass disable queue.sql │ ├── runtime check all database.sql │ ├── kill all conversations.sql │ ├── manage queue.sql │ └── transmission queue.sql ├── !legacy │ └── mirroring.txt ├── bits.sql ├── diagnostics │ ├── procedure cache volume.sql │ ├── who locks.sql │ ├── Object Allocation Unit.sql │ ├── List table with description.sql │ ├── dm_tran_locks details.sql │ ├── show space db.sql │ ├── FindObjects.sql │ ├── wait stats.sql │ └── Тяжелые запросы.sql ├── backup restore │ ├── backup log script.sql │ ├── monitor backup restore database.sql │ ├── README.txt │ ├── restore log from more files.sql │ └── backup all databases.sql ├── RS │ └── Find report by user or group.sql ├── clr │ ├── account │ │ ├── make.cmd │ │ ├── AssemblyInfo.cs │ │ ├── README.md │ │ └── AccountChecksum.cs │ ├── shred_xml │ │ ├── make.cmd │ │ └── AssemblyInfo.cs │ ├── compress │ │ ├── make.cmd │ │ ├── AssemblyInfo.cs │ │ ├── readme.txt │ │ └── DataCompression.cs │ └── invalid_objects │ │ ├── make.cmd │ │ ├── AssemblyInfo.cs │ │ ├── readme.txt │ │ └── InvalidObject.cs ├── triggers │ └── disable triggers.sql ├── virtual column.sql ├── partitions │ ├── Date to string for part.sql │ └── alter_partition_scheme_safely.sql ├── tunning │ ├── Tunning db.sql │ └── options.sql ├── extended event │ ├── Deadlock_monitor.sql │ ├── RunTimeErrorLog.sql │ └── AuditChanges.sql ├── helpers │ ├── sp_get_object_by_definition.sql │ └── sp_get_object_info_by_name.sql ├── finds │ └── find tables by value field.sql ├── scripting objects DBScriper.sql ├── template set discription tables.sql ├── alwayson │ └── Diagnostic status replica.sql ├── audit │ └── DDL Trigger.sql ├── jobs │ └── cross jobs.sql ├── indexes │ ├── index defrag.sql │ └── index detail show.sql ├── generators │ ├── create class from table.sql │ └── deadlock generator.sql ├── returns log file space used by all running transactions.sql ├── maintenance │ ├── service script.sql │ └── SmartShrink2.sql ├── user grant script.sql └── User grant script v2.sql └── Tutorial └── sql_server ├── Exceptions ├── frameworks for SB.sql └── processed exception sql2008r2.sql ├── Service Broker ├── Service Broker.ssms_suo ├── Between Database │ ├── 01 Create databases.sql │ ├── 03 Create Initiator objects.sql │ ├── 02 Create target objects.sql │ ├── 00 introduce.sql │ ├── Between Database.ssmssqlproj │ └── 04 Begin dialog and Send message.sql ├── Between Instance │ ├── 06 Receive responce and close dialog.sql │ ├── 04 Start Dialog and Send Message.sql │ ├── 05 Receive request and send responce.sql │ ├── 03 Continue TargetInst.sql │ ├── 00 introduce.sql │ ├── Between Instance.ssmssqlproj │ ├── 01 Create TargetInst.sql │ └── 02 Create InitiatorInst.sql ├── Service Broker.ssmssln └── Single Database │ ├── 03 Drop Objects.sql │ ├── 00 introduce.sql │ ├── 01 Single database.sql │ ├── 04 Activate procedure.sql │ ├── Single Database.ssmssqlproj │ └── 02 Begin dialog and send message.sql ├── isnull vs coalesce.sql └── MergeTriggerUsage ├── MergeTriggerUsage ├── 04 Delete.sql ├── 02 Insert.sql ├── 03 Update.sql ├── 05 Merge.sql ├── MergeTriggerUsage.ssmssqlproj └── 01 Create Database.sql └── MergeTriggerUsage.ssmssln /PostgreSQL/pgadmin3_support_10.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgavrikov/databases_scripts/HEAD/PostgreSQL/pgadmin3_support_10.sql -------------------------------------------------------------------------------- /PostgreSQL/top 10 command for admin.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgavrikov/databases_scripts/HEAD/PostgreSQL/top 10 command for admin.sql -------------------------------------------------------------------------------- /SQL Server/!hotfix/sql2017 after CU3.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgavrikov/databases_scripts/HEAD/SQL Server/!hotfix/sql2017 after CU3.sql -------------------------------------------------------------------------------- /SQL Server/buffer pool/dmv buffer pool.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgavrikov/databases_scripts/HEAD/SQL Server/buffer pool/dmv buffer pool.sql -------------------------------------------------------------------------------- /Tutorial/sql_server/Exceptions/frameworks for SB.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgavrikov/databases_scripts/HEAD/Tutorial/sql_server/Exceptions/frameworks for SB.sql -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Service Broker.ssms_suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgavrikov/databases_scripts/HEAD/Tutorial/sql_server/Service Broker/Service Broker.ssms_suo -------------------------------------------------------------------------------- /SQL Server/Service Broker/mass disable queue.sql: -------------------------------------------------------------------------------- 1 | select 'ALTER QUEUE '+QUOTENAME(SCHEMA_NAME(schema_id))+'.'+QUOTENAME(name)+' WITH STATUS = OFF 2 | GO 3 | ',* 4 | from sys.service_queues 5 | where is_ms_shipped = 0 -------------------------------------------------------------------------------- /SQL Server/!legacy/mirroring.txt: -------------------------------------------------------------------------------- 1 | Ручная активация зеркала 2 | 3 | -- Force activate mirror 4 | 5 | ALTER DATABASE [database] SET PARTNER FORCE_SERVICE_ALLOW_DATA_LOSS 6 | 7 | ALTER DATABASE [database] SET PARTNER OFF 8 | 9 | --RESTART SQL Server 10 | 11 | RESTORE DATABASE [database] WITH RECOVERY 12 | -------------------------------------------------------------------------------- /SQL Server/Service Broker/runtime check all database.sql: -------------------------------------------------------------------------------- 1 | select 2 | 'select '''+name+''', to_service_name, count(*), min(enqueue_time) 3 | from '+name+'.sys.transmission_queue 4 | GROUP BY to_service_name 5 | order by 3' 6 | ,* 7 | from sys.databases 8 | where is_broker_enabled = 1 9 | and state_desc = 'ONLINE' -------------------------------------------------------------------------------- /SQL Server/bits.sql: -------------------------------------------------------------------------------- 1 | /*** биты ***/ 2 | 00000001 = 1 = 0x01 (0 бит) 3 | 00000010 = 2 = 0x02 (1 бит) 4 | 00000100 = 4 = 0x04 (2 бит) 5 | 00001000 = 8 = 0x08 (3 бит) 6 | 00010000 = 16 = 0x10 (4 бит) 7 | 00100000 = 32 = 0x20 (5 бит) 8 | 01000000 = 64 = 0x40 (6 бит) 9 | 10000000 = 128 = 0x80 (7 бит) 10 | -------------------------------------------------------------------------------- /SQL Server/diagnostics/procedure cache volume.sql: -------------------------------------------------------------------------------- 1 | -- обьем процедурного кеша в разрезе баз 2 | SELECT db = DB_NAME(t.[dbid]), plan_cache_kb = SUM(size_in_bytes / 1024) 3 | FROM sys.dm_exec_cached_plans p 4 | CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) t 5 | WHERE t.[dbid] < 32767 6 | GROUP BY t.[dbid] 7 | ORDER BY 2 DESC -------------------------------------------------------------------------------- /SQL Server/backup restore/backup log script.sql: -------------------------------------------------------------------------------- 1 | DECLARE @str NVARCHAR(1024) = N'\\tmnt.corp\sqlbackups\ADBackSQL\trn\ADBack\ADBack_'+REPLACE(CONVERT(NVARCHAR(20),GETDATE(),102),'.','_')+'_'+REPLACE(CONVERT(NVARCHAR(20),GETDATE(),114),':','_')+'.trn'; 2 | 3 | BACKUP LOG ADBack 4 | TO DISK = @str 5 | WITH INIT,STATS=5,COMPRESSION 6 | -------------------------------------------------------------------------------- /SQL Server/Service Broker/kill all conversations.sql: -------------------------------------------------------------------------------- 1 | DECLARE @sql VARCHAR(1000) 2 | WHILE EXISTS ( 3 | SELECT 1 4 | FROM sys.conversation_endpoints 5 | ) 6 | BEGIN 7 | 8 | SELECT TOP 1 @sql = 'END CONVERSATION '''+CONVERT(VARCHAR(40),conversation_handle)+''' WITH CLEANUP' 9 | FROM sys.conversation_endpoints 10 | 11 | EXEC (@sql) 12 | END 13 | GO 14 | -------------------------------------------------------------------------------- /SQL Server/RS/Find report by user or group.sql: -------------------------------------------------------------------------------- 1 | -- Поиск каталога / отчета по имени пользователя и права на него 2 | select c.Path,c.Name,r.RoleName 3 | from dbo.Users u 4 | join dbo.PolicyUserRole pu on pu.UserID = u.UserID 5 | join dbo.Catalog c on c.PolicyID = pu.PolicyID 6 | join dbo.Roles r on r.RoleID = pu.RoleID 7 | where u.UserName = 'Allow_Reporting_Service' 8 | -------------------------------------------------------------------------------- /SQL Server/clr/account/make.cmd: -------------------------------------------------------------------------------- 1 | set cc=%windir%\Microsoft.NET\Framework\v4.0.30319\csc.exe 2 | set cc64=%windir%\Microsoft.NET\Framework64\v4.0.30319\csc.exe 3 | %cc64% /out:out\AccountChecksum_x64.dll /target:library /platform:x64 AccountChecksum.cs AssemblyInfo.cs 4 | %cc% /out:out\AccountChecksum_x86.dll /target:library /platform:x86 AccountChecksum.cs AssemblyInfo.cs 5 | -------------------------------------------------------------------------------- /SQL Server/clr/shred_xml/make.cmd: -------------------------------------------------------------------------------- 1 | set cc=%windir%\Microsoft.NET\Framework\v4.0.30319\csc.exe 2 | set cc64=%windir%\Microsoft.NET\Framework64\v4.0.30319\csc.exe 3 | %cc64% /out:out\ClrXmlShredder_x64.dll /target:library /platform:x64 ClrXmlShredder.cs AssemblyInfo.cs 4 | %cc% /out:out\ClrXmlShredder_x86.dll /target:library /platform:x86 ClrXmlShredder.cs AssemblyInfo.cs 5 | -------------------------------------------------------------------------------- /SQL Server/clr/compress/make.cmd: -------------------------------------------------------------------------------- 1 | set cc=%windir%\Microsoft.NET\Framework\v4.0.30319\csc.exe 2 | set cc64=%windir%\Microsoft.NET\Framework64\v4.0.30319\csc.exe 3 | %cc64% /out:out\DataCompression_x64.dll /target:library /platform:x64 DataCompression.cs AssemblyInfo.cs 4 | %cc% /out:out\DataCompression_x86.dll /target:library /platform:x86 DataCompression.cs AssemblyInfo.cs 5 | -------------------------------------------------------------------------------- /SQL Server/clr/invalid_objects/make.cmd: -------------------------------------------------------------------------------- 1 | set cc=%windir%\Microsoft.NET\Framework\v4.0.30319\csc.exe 2 | set cc64=%windir%\Microsoft.NET\Framework64\v4.0.30319\csc.exe 3 | %cc64% /out:out\InvalidObjects_x64.dll /target:library /platform:x64 InvalidObject.cs AssemblyInfo.cs 4 | %cc% /out:out\InvalidObjects_x86.dll /target:library /platform:x86 InvalidObject.cs AssemblyInfo.cs 5 | -------------------------------------------------------------------------------- /Tutorial/sql_server/isnull vs coalesce.sql: -------------------------------------------------------------------------------- 1 | -- isnull is only MSSQL operatior. Use data type for first predicate 2 | declare 3 | @a tinyint = null, 4 | @b int = -1 5 | 6 | select coalesce(@a,@b) 7 | select isnull(@a,@b) 8 | go 9 | 10 | declare 11 | @a decimal(18,2) = null, 12 | @b decimal(22,4) = 1234.5678 13 | 14 | select coalesce(@a,@b) 15 | select isnull(@a,@b) 16 | go 17 | -------------------------------------------------------------------------------- /SQL Server/backup restore/monitor backup restore database.sql: -------------------------------------------------------------------------------- 1 | SELECT session_id as SPID, command, a.text AS Query, start_time, percent_complete, dateadd(second,estimated_completion_time/1000, getdate()) as estimated_completion_time 2 | FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) a 3 | WHERE r.command in ('BACKUP DATABASE','RESTORE DATABASE','BACKUP LOG','RESTORE LOG') -------------------------------------------------------------------------------- /SQL Server/triggers/disable triggers.sql: -------------------------------------------------------------------------------- 1 | -- скрипт для отключения триггеров 2 | select 'disable trigger '+quotename(object_schema_name(tr.object_id))+'.'+quotename(tr.name)+' on '+quotename(schema_name(t.schema_id))+'.'+quotename(t.name)+'; 3 | GO 4 | ' 5 | from sys.triggers tr 6 | inner join sys.tables t 7 | on t.object_id = tr.parent_id 8 | where tr.type = 'TR' 9 | and tr.name like '%repl' 10 | 11 | -------------------------------------------------------------------------------- /SQL Server/virtual column.sql: -------------------------------------------------------------------------------- 1 | select 2 | rdc.*, -- информация о строковых полях 3 | plc.*, -- где расположены данные, но в отдельных колонках 4 | sys.fn_PhysLocFormatter(%%physloc%%) as PhysLocation, -- где расположены данные 5 | %%lockres%% as [lockres], -- идентификатор заблокированного ресурса 6 | p.* 7 | from dbo.Objects p 8 | cross apply sys.fn_RowDumpCracker(%%rowdump%%) rdc 9 | cross apply sys.fn_PhysLocCracker(%%physloc%%) plc -------------------------------------------------------------------------------- /SQL Server/partitions/Date to string for part.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Собирает строку из дат для дотстановки в схемц секционирования. 3 | Пример: '20160101','20160102','20160103',... 4 | */ 5 | DECLARE @r datetime2 = '20140401 00:00:00.0000000' 6 | DECLARE @str VARCHAR(MAX) ='' 7 | 8 | WHILE @r <= '20171231 00:00:00.0000000' BEGIN 9 | SELECT @str = @str +'N'''+CAST(@r AS varchar)+''',' 10 | SET @r = DATEADD(DAY,1,@r) 11 | END 12 | 13 | SELECT @str -------------------------------------------------------------------------------- /SQL Server/backup restore/README.txt: -------------------------------------------------------------------------------- 1 | backup all databases.sql - Бекап всех баз данных на сервере в одно место. 2 | backup log script.sql - Бекап лога отдельной БД в файл вида dbname_YYYYMMDD_HHMISS.trn 3 | monitor backup restore database.sql - Скрипт показывает процент выполнения и оставшееся время для операций BACKUP/RESTORE 4 | restore log from more files.sql - Восстановление БД из нескольких лог файлов. Файлы должны быть отсортированны в алфовитном порядке. 5 | -------------------------------------------------------------------------------- /SQL Server/diagnostics/who locks.sql: -------------------------------------------------------------------------------- 1 | SELECT s.session_id, DB_NAME(s.database_id) AS DBName,s.login_name ,s.host_name,s.program_name,s.host_process_id 2 | ,s.open_transaction_count,s.status 3 | ,r.blocking_session_id,r.last_wait_type,r.wait_resource,r.command,t.text 4 | ,pl.query_plan 5 | FROM sys.dm_exec_sessions s 6 | left join sys.dm_exec_requests r 7 | on s.session_id = r.session_id 8 | OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) t 9 | OUTER APPLY sys.dm_exec_query_plan(r.plan_handle) pl 10 | WHERE 11 | r.blocking_session_id > 0 12 | OR s.session_id IN ( 13 | SELECT blocking_session_id 14 | FROM sys.dm_exec_requests 15 | WHERE blocking_session_id > 0 16 | ); 17 | -------------------------------------------------------------------------------- /SQL Server/tunning/Tunning db.sql: -------------------------------------------------------------------------------- 1 | -- Оптимизация бд, для использования фишек поддерживаемых с SQL 2008/R2 2 | USE [master] 3 | GO 4 | declare @db sysname = 'model' 5 | declare @sql_run nvarchar(1000) = N' 6 | ALTER DATABASE ['+@db+N'] SET ANSI_NULLS ON WITH NO_WAIT 7 | ALTER DATABASE ['+@db+N'] SET ANSI_PADDING ON WITH NO_WAIT 8 | ALTER DATABASE ['+@db+N'] SET ANSI_WARNINGS ON WITH NO_WAIT 9 | ALTER DATABASE ['+@db+N'] SET ARITHABORT ON WITH NO_WAIT 10 | ALTER DATABASE ['+@db+N'] SET CONCAT_NULL_YIELDS_NULL ON WITH NO_WAIT 11 | ALTER DATABASE ['+@db+N'] SET QUOTED_IDENTIFIER ON WITH NO_WAIT 12 | ALTER DATABASE ['+@db+N'] SET NUMERIC_ROUNDABORT OFF WITH NO_WAIT 13 | ' 14 | exec sp_executesql @sql_run 15 | GO 16 | -------------------------------------------------------------------------------- /Tutorial/sql_server/MergeTriggerUsage/MergeTriggerUsage/04 Delete.sql: -------------------------------------------------------------------------------- 1 | delete d 2 | from dbo.MergeTbl d 3 | where Id = 10; 4 | /* 5 | Trigger for deleted rc=1 6 | Trigger for deleted d=1 7 | Trigger after deleted rc=1 8 | Trigger after deleted d=1 9 | Trigger for all rc=1 10 | Trigger for all i=0 11 | Trigger for all d=1 12 | Trigger after all rc=1 13 | Trigger after all i=0 14 | Trigger after all d=1 15 | 16 | (1 row(s) affected) 17 | 18 | */ 19 | 20 | delete d 21 | from dbo.MergeTbl d 22 | where Id in (11,12); 23 | /* 24 | Trigger for deleted rc=2 25 | Trigger for deleted d=2 26 | Trigger after deleted rc=2 27 | Trigger after deleted d=2 28 | Trigger for all rc=2 29 | Trigger for all i=0 30 | Trigger for all d=2 31 | Trigger after all rc=2 32 | Trigger after all i=0 33 | Trigger after all d=2 34 | 35 | (2 row(s) affected) 36 | */ -------------------------------------------------------------------------------- /Tutorial/sql_server/MergeTriggerUsage/MergeTriggerUsage/02 Insert.sql: -------------------------------------------------------------------------------- 1 | use [MergeTriggerSamples] 2 | GO 3 | 4 | insert [dbo].[MergeTbl](Id,FName) 5 | values (10,'EEEEE'); 6 | /* 7 | Trigger for insert rc=1 8 | Trigger for insert i=1 9 | Trigger after insert rc=1 10 | Trigger after insert i=1 11 | Trigger for all rc=1 12 | Trigger for all i=1 13 | Trigger for all d=0 14 | Trigger after all rc=1 15 | Trigger after all i=1 16 | Trigger after all d=0 17 | */ 18 | insert [dbo].[MergeTbl](Id,FName) 19 | values (11,'FFFFF'),(12,'FFFFF'); 20 | /* 21 | Trigger for insert rc=2 22 | Trigger for insert i=2 23 | Trigger after insert rc=2 24 | Trigger after insert i=2 25 | Trigger for all rc=2 26 | Trigger for all i=2 27 | Trigger for all d=0 28 | Trigger after all rc=2 29 | Trigger after all i=2 30 | Trigger after all d=0 31 | 32 | (2 row(s) affected) 33 | */ -------------------------------------------------------------------------------- /SQL Server/extended event/Deadlock_monitor.sql: -------------------------------------------------------------------------------- 1 | create event session [Deadlock_monitor] on server 2 | add event sqlserver.xml_deadlock_report( 3 | action(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.database_id,sqlserver.database_name,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.server_instance_name,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.sql_text)) 4 | add target package0.event_file(set filename=N'D:\MSSQL\Audit\Deadlock_monitor.xel',max_file_size=(100)), 5 | add target package0.ring_buffer(set max_events_limit=(0),max_memory=(4096)) 6 | with (max_memory=102400 kb,event_retention_mode=allow_multiple_event_loss,max_dispatch_latency=60 seconds,max_event_size=0 kb,memory_partition_mode=per_node,track_causality=on,startup_state=off) 7 | go 8 | 9 | 10 | -------------------------------------------------------------------------------- /SQL Server/helpers/sp_get_object_by_definition.sql: -------------------------------------------------------------------------------- 1 | USE [master] 2 | GO 3 | SET ANSI_NULLS ON 4 | GO 5 | SET QUOTED_IDENTIFIER ON 6 | GO 7 | CREATE procedure [dbo].[sp_get_object_by_definition] 8 | @pattern nvarchar(max) 9 | as 10 | begin 11 | /* 12 | Author: Dmitriy Gavrikov 13 | Note: for hotkey in SSMS 14 | */ 15 | declare @sql varchar(4000) = 16 | 'select 17 | O.name as [object_name] 18 | ,quotename(schema_name(O.schema_id))+''.''+quotename(O.name) 19 | as [full_name] 20 | ,O.object_id 21 | ,O.parent_object_id 22 | ,O.type 23 | ,O.type_desc 24 | ,O.create_date 25 | ,O.modify_date 26 | ,O.is_ms_shipped 27 | ,M.definition 28 | from 29 | sys.all_objects O 30 | inner join sys.sql_modules M on O.object_id = M.object_id 31 | where 32 | M.definition like N''%'+@pattern + '%'' 33 | order by 34 | O.name'; 35 | exec(@sql); 36 | end 37 | -------------------------------------------------------------------------------- /SQL Server/helpers/sp_get_object_info_by_name.sql: -------------------------------------------------------------------------------- 1 | USE [master] 2 | GO 3 | SET ANSI_NULLS ON 4 | GO 5 | SET QUOTED_IDENTIFIER ON 6 | GO 7 | ALTER procedure [dbo].[sp_get_object_info_by_name] 8 | @object_name sysname 9 | as 10 | begin 11 | /* 12 | Author: Dmitriy Gavrikov 13 | Note: for hotkey in SSMS 14 | */ 15 | declare @sql varchar(2000); 16 | 17 | set @sql = ' 18 | select 19 | O.name as [object_name] 20 | ,quotename(schema_name(O.schema_id))+''.''+quotename(O.name) 21 | as [full_name] 22 | ,O.object_id 23 | ,O.parent_object_id 24 | ,O.type 25 | ,O.type_desc 26 | ,O.create_date 27 | ,O.modify_date 28 | ,O.is_ms_shipped 29 | ,M.definition 30 | from 31 | sys.all_objects O 32 | left join sys.sql_modules M on O.object_id = M.object_id 33 | where 34 | name like N'''+@object_name + '%'' 35 | order by 36 | O.name'; 37 | exec (@sql); 38 | end 39 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Database/01 Create databases.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Создание баз данных и установка параметра доверительных отношений 3 | 4 | По умолчанию в новых базах данных включен параметр ENABLE_BROKER. Установка параметра TRUSTWORTHY 5 | в базе данных InitiatorDB позволяет начинать диалоги с целевыми службами в базе данных TargetDB. 6 | */ 7 | 8 | USE [master]; 9 | GO 10 | 11 | IF EXISTS (SELECT * FROM sys.databases 12 | WHERE name = N'TargetDB') 13 | DROP DATABASE TargetDB; 14 | GO 15 | CREATE DATABASE TargetDB; 16 | GO 17 | 18 | ALTER DATABASE TargetDB SET ENABLE_BROKER 19 | GO 20 | 21 | IF EXISTS (SELECT * FROM sys.databases 22 | WHERE name = N'InitiatorDB') 23 | DROP DATABASE InitiatorDB; 24 | GO 25 | CREATE DATABASE InitiatorDB; 26 | GO 27 | ALTER DATABASE InitiatorDB SET ENABLE_BROKER 28 | GO 29 | ALTER DATABASE InitiatorDB SET TRUSTWORTHY ON; 30 | GO -------------------------------------------------------------------------------- /SQL Server/diagnostics/Object Allocation Unit.sql: -------------------------------------------------------------------------------- 1 | /*распределение страниц данных, с указанием файловой группы, объекта и индекса, которые эти страницы охватывают. */ 2 | 3 | SELECT au.allocation_unit_id 4 | ,au.type_desc 5 | ,au.total_pages 6 | ,au.used_pages 7 | ,au.data_pages 8 | ,p.index_id 9 | ,i.name AS [indexname] 10 | ,i.type_desc AS [index_type] 11 | ,fg.name AS [filegroup] 12 | ,s.name AS [schema] 13 | ,o.name AS [Object] 14 | ,o.type_desc 15 | ,p.data_compression_desc 16 | FROM sys.system_internals_allocation_units au 17 | JOIN sys.partitions [p] ON [p].[partition_id] = au.[container_id] 18 | JOIN sys.filegroups fg ON au.filegroup_id = fg.data_space_id 19 | JOIN sys.objects o ON o.object_id = p.object_id 20 | JOIN sys.schemas s ON s.schema_id = o.schema_id 21 | JOIN sys.indexes i ON i.object_id = o.object_id AND i.index_id = p.index_id 22 | WHERE o.name = 'CandlesHistory' 23 | ORDER BY total_pages desc 24 | 25 | -------------------------------------------------------------------------------- /SQL Server/finds/find tables by value field.sql: -------------------------------------------------------------------------------- 1 | declare @tbl table (cnt int not null,query nvarchar(4000)) 2 | declare @tbl_res table (cnt int not null,query nvarchar(4000)) 3 | declare @sql_text nvarchar(4000) ; 4 | declare @param_def nvarchar(500)='@cnt int output'; 5 | declare @cnt int; 6 | insert @tbl ( cnt, query ) 7 | select 0,'select @cnt = count(*) from '+quotename(object_schema_name(c.object_id))+'.'+quotename(object_name(c.object_id))+ ' with (nolock) where IdObject = 399610' 8 | from sys.columns c 9 | where name = 'IdObject' 10 | and object_schema_name(c.object_id) not in ('sys','hist','tmp','Logs') 11 | 12 | while exists (select 1 from @tbl where cnt = 0) begin 13 | select top 1 14 | @sql_text = query 15 | from @tbl; 16 | exec sp_executesql @sql_text,@param_def ,@cnt = @cnt output; 17 | if @cnt > 0 18 | insert into @tbl_res( cnt, query )values (@cnt,@sql_text); 19 | delete @tbl where query = @sql_text; 20 | 21 | end; 22 | 23 | select * from @tbl_res; -------------------------------------------------------------------------------- /Tutorial/sql_server/MergeTriggerUsage/MergeTriggerUsage.ssmssln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # SQL Server Management Studio Solution File, Format Version 13.00 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{4F2E2C19-372F-40D8-9FA7-9D2138C6997A}") = "MergeTriggerUsage", "MergeTriggerUsage\MergeTriggerUsage.ssmssqlproj", "{4DE61F00-A328-417D-A507-E53BBF17BF6A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Default|Default = Default|Default 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {4DE61F00-A328-417D-A507-E53BBF17BF6A}.Default|Default.ActiveCfg = Default 14 | {2B641416-8291-47D1-A757-F24A17F48195}.Default|Default.ActiveCfg = Default 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Exceptions/processed exception sql2008r2.sql: -------------------------------------------------------------------------------- 1 | declare @str varchar(20) 2 | declare @err_text varchar(4000)=''; 3 | 4 | begin try 5 | set xact_abort on; 6 | --select 1/0; 7 | raiserror ('Необходимо заполнить параметр %s',17,1,@str); 8 | end try 9 | begin catch 10 | declare 11 | @err_number int = error_number(), 12 | @err_message varchar(2000) = error_message(), 13 | @err_line int = error_line(), 14 | @err_proc sysname = error_procedure(), 15 | @err_severity int = error_severity(), 16 | @err_state int = error_state(); 17 | 18 | set @err_text = 'Ошибка #'+isnull(cast(@err_number as varchar),'') 19 | + ' в процедуре ['+isnull(@err_proc,'')+'] в строке #' 20 | +isnull(cast(@err_line as varchar),'')+': '+isnull(@err_message,''); 21 | 22 | if xact_state() in (-1,1) and @@trancount > 0 23 | rollback; 24 | 25 | raiserror(@err_text,@err_severity,@err_state); 26 | end catch 27 | 28 | select @err_text; -------------------------------------------------------------------------------- /Tutorial/sql_server/MergeTriggerUsage/MergeTriggerUsage/03 Update.sql: -------------------------------------------------------------------------------- 1 | update mt set FName = lower(FName) 2 | from [dbo].[MergeTbl] mt 3 | where Id = 11; 4 | /* 5 | Trigger for update rc=1 6 | Trigger for update i=1 7 | Trigger for update d=1 8 | Trigger after update rc=1 9 | Trigger after update i=1 10 | Trigger after update d=1 11 | Trigger for all rc=1 12 | Trigger for all i=1 13 | Trigger for all d=1 14 | Trigger after all rc=1 15 | Trigger after all i=1 16 | Trigger after all d=1 17 | 18 | (1 row(s) affected) 19 | */ 20 | 21 | update mt set FName = upper(FName) 22 | from [dbo].[MergeTbl] mt 23 | where Id in (11,12); 24 | /* 25 | Trigger for update rc=2 26 | Trigger for update i=2 27 | Trigger for update d=2 28 | Trigger after update rc=2 29 | Trigger after update i=2 30 | Trigger after update d=2 31 | Trigger for all rc=2 32 | Trigger for all i=2 33 | Trigger for all d=2 34 | Trigger after all rc=2 35 | Trigger after all i=2 36 | Trigger after all d=2 37 | 38 | (2 row(s) affected) 39 | 40 | */ -------------------------------------------------------------------------------- /SQL Server/scripting objects DBScriper.sql: -------------------------------------------------------------------------------- 1 | select 'D:\Work\DBScripter\DBScripter.exe server='+cast(serverproperty('MachineName') as varchar)+' db='+name+' out=d:\Project\SQL\source\' 2 | from sys.databases d 3 | outer apply ( 4 | select 5 | case when 6 | d.state_desc = 'ONLINE' 7 | and d.is_read_only = 0 8 | and 9 | ( 10 | hars.replica_id is null 11 | or 12 | ( 13 | hars.is_local = 1 14 | and isnull(hars.[role], 3) = 1 15 | ) 16 | ) 17 | then 1 18 | else 0 19 | end [Status] 20 | from sys.dm_hadr_availability_replica_states hars 21 | where d.database_id = iif(d.name is null, db_id(), db_id(d.name)) and d.replica_id = hars.replica_id 22 | 23 | ) wr 24 | where name not in ('master','tempdb','msdb','model','SSISDB') 25 | and isnull(wr.Status,1) = 1 26 | order by name 27 | 28 | 29 | -------------------------------------------------------------------------------- /SQL Server/backup restore/restore log from more files.sql: -------------------------------------------------------------------------------- 1 | Restore tlog from disk 2 | declare 3 | @path varchar(230), 4 | @run varchar(250), 5 | @flname varchar(255) 6 | set @path = '\\bgfmskswdias1\tlog\' -- не забываем про черточку 7 | 8 | if (object_id('tempdb..##RestoreTLog') is not null) drop table ##RestoreTLog 9 | create table ##RestoreTLog (flname varchar(255)) 10 | 11 | set @run = 'dir '+@path+'*.trn /b /a:-d /o:n' 12 | insert into ##RestoreTLog 13 | exec xp_cmdshell @run 14 | 15 | declare c1 cursor 16 | for select (@path+ltrim(rtrim(flname))) as flname from ##RestoreTLog where flname is not null 17 | 18 | open c1 19 | FETCH NEXT FROM c1 into @flname 20 | WHILE @@FETCH_STATUS = 0 21 | BEGIN 22 | /***************************/ 23 | /* тут обработка */ 24 | /***************************/ 25 | RESTORE LOG [workdb] 26 | FROM DISK = @flname 27 | WITH FILE = 1, NORECOVERY, NOUNLOAD, STATS = 10 28 | /***************************/ 29 | 30 | FETCH NEXT FROM c1 into @flname 31 | END 32 | 33 | close c1 DEALLOCATE c1 34 | 35 | if (object_id('tempdb..##RestoreTLog') is not null) drop table ##RestoreTLog 36 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Instance/06 Receive responce and close dialog.sql: -------------------------------------------------------------------------------- 1 | USE InstInitiatorDB; 2 | GO 3 | 4 | /* 5 | Получение ответа и завершение диалога 6 | 7 | Чтобы получить ответное сообщение и завершить диалог. Инструкция RECEIVE получает ответное 8 | сообщение из очереди InstInitiatorQueue. Инструкция END CONVERSATION завершает работу 9 | инициирующей стороны диалога. Последняя инструкция SELECT отображает текст ответного сообщения 10 | так, чтобы можно было подтвердить его идентичность сообщению, отправленному на предыдущем шаге. 11 | */ 12 | DECLARE @RecvReplyMsg NVARCHAR(100); 13 | DECLARE @RecvReplyDlgHandle UNIQUEIDENTIFIER; 14 | 15 | BEGIN TRANSACTION; 16 | 17 | WAITFOR 18 | ( RECEIVE TOP(1) 19 | @RecvReplyDlgHandle = conversation_handle, 20 | @RecvReplyMsg = message_body 21 | FROM InstInitiatorQueue 22 | ), TIMEOUT 1000; 23 | 24 | END CONVERSATION @RecvReplyDlgHandle; 25 | 26 | -- Display recieved request. 27 | SELECT @RecvReplyMsg AS ReceivedReplyMsg; 28 | 29 | COMMIT TRANSACTION; 30 | GO 31 | 32 | 33 | /* 34 | SELECT * 35 | FROM [dbo].[InstTargetQueue] 36 | 37 | SELECT * 38 | FROM sys.transmission_queue 39 | */ -------------------------------------------------------------------------------- /SQL Server/partitions/alter_partition_scheme_safely.sql: -------------------------------------------------------------------------------- 1 | declare @is_deadlock int = 0, @Day datetime = convert(date, getdate()), @s varchar(100) = '', @err_num int, @err_mes nvarchar(100) 2 | 3 | L_NEW_LAP: 4 | 5 | begin try 6 | 7 | select 8 | @is_deadlock = 0 9 | ,@Day = '2010-09-01 00:00:00.000' 10 | ,@s = ''; 11 | 12 | while @Day > '2008' 13 | begin 14 | 15 | if not exists 16 | ( 17 | select * 18 | from sys.partition_range_values prv 19 | inner join sys.partition_functions pf 20 | on pf.function_id = prv.function_id 21 | where pf.name = 'DateRangePF' 22 | and value = @Day 23 | ) 24 | begin 25 | set @s = convert(varchar(20), @Day, 112); 26 | raiserror('@Day = %s', 10, 1, @s) with NOWAIT; 27 | 28 | ALTER PARTITION SCHEME [DateRangePS] 29 | NEXT USED [PRIMARY]; 30 | 31 | ALTER PARTITION FUNCTION [DateRangePF]() 32 | SPLIT RANGE (@Day); 33 | end 34 | 35 | SET @Day = DATEADD(DAY, -1, @Day); 36 | 37 | end 38 | 39 | end try 40 | begin catch 41 | 42 | select 43 | @err_num = ERROR_NUMBER() 44 | ,@err_mes = ERROR_MESSAGE() 45 | 46 | if @err_num = 1205 47 | and @err_mes like '%deadlock%' 48 | set @is_deadlock = 1 49 | 50 | raiserror('error! %d %s',10,1,@err_num,@err_mes) with NOWAIT; 51 | 52 | end catch 53 | 54 | if @is_deadlock = 1 55 | GOTO L_NEW_LAP; -------------------------------------------------------------------------------- /SQL Server/template set discription tables.sql: -------------------------------------------------------------------------------- 1 | with tablesInfo as ( 2 | select sch.name [sch], tab.name [tab], col.name [col], isnull(cast(ep.value as nvarchar), '') [description], tab.object_id [tab_object_id] 3 | from 4 | sys.schemas sch 5 | inner join 6 | sys.tables tab 7 | on 8 | tab.schema_id = sch.schema_id 9 | and sch.name not in ('sys') 10 | inner join 11 | sys.columns col 12 | on col.object_id = tab.object_id 13 | left outer join 14 | sys.extended_properties ep 15 | on ep.major_id = tab.object_id and ep.minor_id = col.column_id 16 | ) 17 | ,tabNames as ( 18 | select distinct ti.sch, ti.tab, isnull(cast(ep.value as nvarchar), '') [description] 19 | from 20 | tablesInfo ti 21 | left outer join 22 | sys.extended_properties ep 23 | on ep.major_id = ti.[tab_object_id] and ep.minor_id = 0 24 | ) 25 | select tabNames.sch, tabNames.tab, 26 | 'execute [sysAdd].[AddColumnDescription] 27 | '''+tabNames.sch+''', '''+tabNames.tab+''', '''+tabNames.[description]+''' '+(select [sysAdd].[Concatenate](' 28 | , '''+ti.col+''', '''+ti.[description]+'''') 29 | from 30 | tablesInfo ti 31 | where ti.tab = tabNames.tab and ti.col != 'versionId')+'' [AddComment] 32 | from 33 | tabNames tabNames 34 | order by 35 | tabNames.sch, tabNames.tab -------------------------------------------------------------------------------- /SQL Server/extended event/RunTimeErrorLog.sql: -------------------------------------------------------------------------------- 1 | create event session [RunTimeErrorLog] on server 2 | add event sqlserver.error_reported( 3 | action(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.server_principal_sid,sqlserver.session_id,sqlserver.session_nt_username,sqlserver.session_server_principal_name,sqlserver.sql_text,sqlserver.username) 4 | where ([package0].[not_equal_int64]([error_number],(156)) and [package0].[not_equal_int64]([error_number],(8153)) and [package0].[not_equal_int64]([error_number],(5703)) and [package0].[not_equal_int64]([error_number],(5701)) and [package0].[not_equal_int64]([error_number],(102)) and [package0].[greater_than_int64]([severity],(10)) and [package0].[less_than_int64]([error_number],(50000)) and [package0].[not_equal_int64]([error_number],(8152)) and [package0].[not_equal_int64]([error_number],(1222)))) 5 | add target package0.event_file(set filename=N'D:\MSSQL\Audit\RunTimeErrorLog',max_file_size=(100),max_rollover_files=(10)) 6 | with (max_memory=102400 kb,event_retention_mode=allow_multiple_event_loss,max_dispatch_latency=60 seconds,max_event_size=0 kb,memory_partition_mode=per_node,track_causality=on,startup_state=on) 7 | go 8 | 9 | 10 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Service Broker.ssmssln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # SQL Server Management Studio Solution File, Format Version 12.00 4 | Project("{4F2E2C19-372F-40D8-9FA7-9D2138C6997A}") = "Single Database", "Single Database\Single Database.ssmssqlproj", "{E1F0C370-4ABF-4299-9C61-2B8BFD81A5CA}" 5 | EndProject 6 | Project("{4F2E2C19-372F-40D8-9FA7-9D2138C6997A}") = "Between Database", "Between Database\Between Database.ssmssqlproj", "{DCF9C718-9BA6-430C-98C7-1519223389A2}" 7 | EndProject 8 | Project("{4F2E2C19-372F-40D8-9FA7-9D2138C6997A}") = "Between Instance", "Between Instance\Between Instance.ssmssqlproj", "{8B304680-291E-40A7-994B-6862AB319467}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Default|Default = Default|Default 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {E1F0C370-4ABF-4299-9C61-2B8BFD81A5CA}.Default|Default.ActiveCfg = Default 16 | {22CCE029-379F-4CF7-9639-1918BA71F42C}.Default|Default.ActiveCfg = Default 17 | {DCF9C718-9BA6-430C-98C7-1519223389A2}.Default|Default.ActiveCfg = Default 18 | {8B304680-291E-40A7-994B-6862AB319467}.Default|Default.ActiveCfg = Default 19 | EndGlobalSection 20 | GlobalSection(SolutionProperties) = preSolution 21 | HideSolutionNode = FALSE 22 | EndGlobalSection 23 | EndGlobal 24 | -------------------------------------------------------------------------------- /SQL Server/alwayson/Diagnostic status replica.sql: -------------------------------------------------------------------------------- 1 | -- 1. Диагностические запросы показывают, что все реплики в норме 2 | SELECT r.replica_server_name 3 | , rs.database_id 4 | , DB_NAME(rs.database_id) AS [DatabaseName] 5 | , ISNULL(DATEDIFF(SECOND, rs.last_commit_time, prs.last_commit_time), 0) AS [SecsBehindPrimary] 6 | , prs.last_commit_time AS [Primary_last_commit_time] 7 | , rs.last_commit_time AS [Secondary_last_commit_time] 8 | , rs.last_redone_time AS [Secondary_last_redone_time] 9 | FROM sys.dm_hadr_database_replica_states rs 10 | JOIN sys.availability_replicas r ON r.group_id = rs.group_id 11 | AND r.replica_id = rs.replica_id 12 | JOIN sys.dm_hadr_database_replica_states prs ON r.group_id = prs.group_id 13 | AND prs.group_database_id = rs.group_database_id 14 | AND rs.is_local = 0 15 | AND prs.is_primary_replica = 1 16 | --WHERE DB_NAME(rs.database_id) = 'hell' 17 | ORDER BY DB_NAME(rs.database_id), r.replica_server_name; 18 | 19 | SELECT rs.redo_queue_size, * 20 | FROM sys.dm_hadr_database_replica_states rs 21 | JOIN sys.availability_replicas r ON r.group_id = rs.group_id 22 | AND r.replica_id = rs.replica_id 23 | WHERE --rs.database_id = 13 24 | --AND r.replica_server_name = @@SERVERNAME 25 | rs.redo_queue_size IS NOT NULL; 26 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Database/03 Create Initiator objects.sql: -------------------------------------------------------------------------------- 1 | USE InitiatorDB; 2 | GO 3 | /* 4 | Создание типов сообщений 5 | 6 | Указанные здесь имена и свойства типов сообщений должны быть идентичны тем, 7 | которые были созданы в базе данных TargetDB на предыдущем занятии. 8 | */ 9 | CREATE MESSAGE TYPE [//BothDB/2DBSample/RequestMessage] 10 | VALIDATION = WELL_FORMED_XML; 11 | CREATE MESSAGE TYPE [//BothDB/2DBSample/ReplyMessage] 12 | VALIDATION = WELL_FORMED_XML; 13 | GO 14 | /* 15 | Создание контракта 16 | 17 | Указанное здесь имя и свойства контракта должны быть идентичны имени и 18 | свойствам контракта, который был создан в базе данных TargetDB на 19 | предыдущем занятии. 20 | */ 21 | CREATE CONTRACT [//BothDB/2DBSample/SimpleContract] 22 | ([//BothDB/2DBSample/RequestMessage] 23 | SENT BY INITIATOR, 24 | [//BothDB/2DBSample/ReplyMessage] 25 | SENT BY TARGET 26 | ); 27 | GO 28 | /* 29 | Создание очереди и службы инициирующей стороны 30 | 31 | Затем запустите его, чтобы создать очередь и службу, которые будут использоваться 32 | для инициирующей стороны. Поскольку не указано имя контракта, никакие другие 33 | службы не могут использовать эту службу в качестве целевой. 34 | */ 35 | CREATE QUEUE InitiatorQueue2DB; 36 | 37 | CREATE SERVICE [//InitDB/2DBSample/InitiatorService] 38 | ON QUEUE InitiatorQueue2DB; 39 | GO 40 | 41 | -------------------------------------------------------------------------------- /SQL Server/backup restore/backup all databases.sql: -------------------------------------------------------------------------------- 1 | declare @dbname nvarchar(128), 2 | @sqlrun nvarchar(1024), 3 | @path nvarchar(128), 4 | @backupSetId as int, 5 | @dbfile nvarchar(256) 6 | declare c insensitive cursor for select [name] from sys.databases where [name] not in ('tempdb','master','msdb','model') 7 | set @path = 'd:\base\backup\' 8 | open c 9 | fetch next from c into @dbname 10 | while @@fetch_status = 0 11 | begin 12 | set @sqlrun = 'BACKUP DATABASE ['+@dbname+'] TO DISK = N'''+@path+@@servername+'_'+@dbname+'_' 13 | +replace(convert(nvarchar,getdate(),102),'.','_')+'.bak'' WITH NOFORMAT, INIT, NAME = N''' 14 | +@dbname+'-Full Database Backup'',SKIP, NOREWIND, NOUNLOAD, STATS = 10' 15 | exec sp_executesql @sqlrun 16 | set @dbfile = @path+@@servername+'_'+@dbname+'_'+replace(convert(nvarchar,getdate(),102),'.','_')+'.bak' 17 | select @backupSetId = position from msdb..backupset where database_name=@dbname and backup_set_id=(select max(backup_set_id) from msdb..backupset where database_name=@dbname ) 18 | if @backupSetId is not null 19 | RESTORE VERIFYONLY FROM DISK = @dbfile WITH FILE = @backupSetId, NOUNLOAD, NOREWIND 20 | fetch next from c into @dbname 21 | end 22 | close c 23 | deallocate c 24 | 25 | 26 | SELECT 27 | 'BACKUP DATABASE '+QUOTENAME(name)+ ' 28 | TO DISK = N''\\10.77.19.2\backup$\processing.backup\'+name+'_full.bak'' 29 | WITH INIT, COPY_ONLY, STATS=5 30 | GO 31 | ' 32 | FROM sys.databases 33 | WHERE database_id > 4 34 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Single Database/03 Drop Objects.sql: -------------------------------------------------------------------------------- 1 | IF EXISTS (SELECT * FROM sys.services 2 | WHERE name = 3 | N'//SSBSExample/SingleDB/TargetService') 4 | DROP SERVICE 5 | [//SSBSExample/SingleDB/TargetService]; 6 | 7 | IF EXISTS (SELECT * FROM sys.service_queues 8 | WHERE name = N'TargetQueue') 9 | DROP QUEUE TargetQueue; 10 | 11 | -- Drop the intitator queue and service if they already exist. 12 | IF EXISTS (SELECT * FROM sys.services 13 | WHERE name = 14 | N'//SSBSExample/SingleDB/InitiatorService') 15 | DROP SERVICE 16 | [//SSBSExample/SingleDB/InitiatorService]; 17 | 18 | IF EXISTS (SELECT * FROM sys.service_queues 19 | WHERE name = N'InitiatorQueue') 20 | DROP QUEUE InitiatorQueue; 21 | 22 | IF EXISTS (SELECT * FROM sys.service_contracts 23 | WHERE name = 24 | N'//SSBSExample/SingleDB/SingleContract') 25 | DROP CONTRACT 26 | [//SSBSExample/SingleDB/SingleContract]; 27 | 28 | IF EXISTS (SELECT * FROM sys.service_message_types 29 | WHERE name = 30 | N'//SSBSExample/SingleDB/RequestMessage') 31 | DROP MESSAGE TYPE 32 | [//SSBSExample/SingleDB/RequestMessage]; 33 | 34 | IF EXISTS (SELECT * FROM sys.service_message_types 35 | WHERE name = 36 | N'//SSBSExample/SingleDB/ResponceMessage') 37 | DROP MESSAGE TYPE 38 | [//SSBSExample/SingleDB/ResponceMessage]; 39 | GO -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Instance/04 Start Dialog and Send Message.sql: -------------------------------------------------------------------------------- 1 | USE InstInitiatorDB; 2 | GO 3 | /* 4 | Начало диалога и отправка сообщения-запроса 5 | 6 | Чтобы начать диалог, и направьте сообщение-запрос целевой службе 7 | //TgtDB/2InstSample/TargetService в базе данных InstTargetDB. Этот код необходимо запускать 8 | единым блоком, поскольку для передачи дескриптора диалога из инструкции BEGIN DIALOG в 9 | инструкцию SEND используется переменная. Пакет выполняет инструкцию BEGIN DIALOG для начала 10 | диалога, а затем создает сообщение-запрос. Затем в инструкции SEND используется дескриптор 11 | диалога для отправки в этом диалоге сообщения-запроса. Последняя инструкция SELECT просто 12 | отображает текст отправленного сообщения. 13 | */ 14 | DECLARE @InitDlgHandle UNIQUEIDENTIFIER; 15 | DECLARE @RequestMsg NVARCHAR(100); 16 | 17 | BEGIN TRANSACTION; 18 | 19 | BEGIN DIALOG @InitDlgHandle 20 | FROM SERVICE [//InstDB/2InstSample/InitiatorService] 21 | TO SERVICE N'//TgtDB/2InstSample/TargetService' 22 | ON CONTRACT [//BothDB/2InstSample/SimpleContract] 23 | WITH 24 | ENCRYPTION = ON; 25 | 26 | SELECT @RequestMsg = N'Message for Target service.'; 27 | 28 | SEND ON CONVERSATION @InitDlgHandle 29 | MESSAGE TYPE [//BothDB/2InstSample/RequestMessage] 30 | (@RequestMsg); 31 | 32 | SELECT @RequestMsg AS SentRequestMsg; 33 | 34 | COMMIT TRANSACTION; 35 | GO 36 | /* 37 | SELECT * 38 | FROM [dbo].[InstInitiatorQueue] 39 | 40 | SELECT * 41 | FROM sys.transmission_queue 42 | */ -------------------------------------------------------------------------------- /SQL Server/Service Broker/manage queue.sql: -------------------------------------------------------------------------------- 1 | -- список sysxmitqueue 2 | SELECT p.[rows] as [XmitQ Depth] 3 | FROM sys.objects as o JOIN sys.partitions AS p 4 | ON p.object_id = o.object_id 5 | WHERE o.name = 'sysxmitqueue' 6 | 7 | SELECT TOP 1 dateadd(hour, 3, enqueue_time) as enqueue_time 8 | FROM [sys].[transmission_queue] WITH (NOLOCK) 9 | ORDER BY enqueue_time ASC 10 | 11 | -- статусы очередей 12 | SELECT state_desc,COUNT(*) 13 | FROM sys.conversation_endpoints WITH (NOLOCK) 14 | GROUP BY state_desc 15 | 16 | -- скрипт по закрытию. 17 | SELECT 'END CONVERSATION '''+CONVERT(VARCHAR(36),conversation_handle)+''' WITH CLEANUP 18 | GO 19 | ',far_service,far_broker_instance 20 | FROM sys.conversation_endpoints 21 | WHERE state_desc = 'CLOSED' 22 | far_service = 'http://alfa-direct.ru/SQL/_Queue/managers_InitiatorService_ADBACKSQL_ADBACKSQL' 23 | 24 | -- скрипт по закрытию с проверкой сообщений. 25 | SELECT distinct 'END CONVERSATION '''+CONVERT(VARCHAR(36),ce.conversation_handle)+''' WITH CLEANUP 26 | GO 27 | ',far_service,far_broker_instance 28 | FROM sys.conversation_endpoints ce 29 | left join sys.transmission_queue tq 30 | on tq.conversation_handle = ce.conversation_handle 31 | WHERE state_desc = 'CLOSED' 32 | and tq.conversation_handle is null 33 | 34 | -- чистка дополнительных таблиц 35 | SELECT COUNT(*) 36 | --DELETE sc 37 | FROM orders.SessionConversations sc 38 | LEFT JOIN sys.conversation_endpoints ce 39 | ON ce.conversation_handle = sc.Handle 40 | WHERE ce.conversation_handle IS NULL 41 | -- чистка дополнительных таблиц 42 | 43 | 44 | SELECT DISTINCT far_service 45 | FROM sys.conversation_endpoints 46 | -------------------------------------------------------------------------------- /SQL Server/clr/account/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AccountChecksum")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Dmitriy Gavrikov")] 12 | [assembly: AssemblyProduct("SQLCLR.AccountChecksum")] 13 | [assembly: AssemblyCopyright("Copyright © Dmitriy Gavrikov 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("af74e80d-e7b9-4c68-a75f-46bc8e2d3202")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SQL Server/clr/compress/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DataCompression")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Dmitriy Gavrikov")] 12 | [assembly: AssemblyProduct("SQLCLR.DataCompression")] 13 | [assembly: AssemblyCopyright("Copyright © Dmitriy Gavrikov 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5d4cd4ce-9832-4ac1-b2d1-2f8c282b8237")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SQL Server/clr/shred_xml/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ClrXmlShredder")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Dmitriy Gavrikov")] 12 | [assembly: AssemblyProduct("SQLCLR.ClrXmlShredder")] 13 | [assembly: AssemblyCopyright("Copyright © Dmitriy Gavrikov 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("950a7896-bfb6-42c6-9f29-70c411f986e0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SQL Server/clr/invalid_objects/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("InvalidObject")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Dmitriy Gavrikov")] 12 | [assembly: AssemblyProduct("SQLCLR.InvalidObject")] 13 | [assembly: AssemblyCopyright("Copyright © Dmitriy Gavrikov 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d0d3f4f4-e4f6-4c40-981e-9350ad3516bd")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SQL Server/clr/compress/readme.txt: -------------------------------------------------------------------------------- 1 | [Info] 2 | This assembly include two function for compress and decompress stream. 3 | fnCompress - compress input stream and return compressed varbinary(max). 4 | fnDecompress - decompress input stream and return decompressed varbinary(max). 5 | 6 | [Install] 7 | sp_configure 'advanced options',1; 8 | GO 9 | reconfigure with override; 10 | GO 11 | sp_configure 'clr enabled',1 12 | GO 13 | reconfigure with override; 14 | GO 15 | 16 | create assembly [DataCompression] 17 | from 'c:\clr\DataCompression_x64.dll' 18 | with permission_set = safe; 19 | GO 20 | 21 | create function dbo.fnCompress(@inputStream varbinary(max)) returns varbinary(max) 22 | as external name DataCompression.DataCompression.fnCompress 23 | GO 24 | 25 | create function dbo.fnDecompress(@inputStream varbinary(max)) returns varbinary(max) 26 | as external name DataCompression.DataCompression.fnDecompress 27 | GO 28 | 29 | -------- 30 | Examples 31 | -------- 32 | 33 | declare @inputData nvarchar(4000); 34 | declare @outData nvarchar(4000); 35 | declare @cData varbinary(max) 36 | 37 | select @inputData = replicate('Welcome!',500); 38 | select datalength(@inputData) as [input DataLength],hashbytes('MD5',@inputData) as [Input HashMD5] 39 | 40 | select @cData = dbo.fnCompress(cast(@inputData as varbinary(max))); 41 | select datalength(@cData) as [compress DataLength],hashbytes('MD5',@cData) as [Compress HashMD5] 42 | 43 | select @outData = cast(dbo.fnDecompress(@cData) as nvarchar(max)); 44 | select datalength(@outData) as [Output DataLength],hashbytes('MD5',@outData) as [Output HashMD5] 45 | 46 | select iif(@outData = @inputData,'Equal','Not Equal') as Compare 47 | GO -------------------------------------------------------------------------------- /SQL Server/diagnostics/List table with description.sql: -------------------------------------------------------------------------------- 1 | --—крипт для вытаскивания всех таблиц и их полей с описаниями 2 | ;with allDescr as ( 3 | select col.name [objName], isnull(ep.value, '') [MS_Description], col.column_id, col.object_id 4 | , typ.name 5 | , case 6 | when col.max_length = -1 7 | then 'max' 8 | when typ.name = 'nvarchar' 9 | then cast(col.max_length/2 as nvarchar) 10 | else '' end max_length 11 | , case when col.is_nullable = 0 then 'not null' else 'null' end is_nullable 12 | , cast(col.max_length as nvarchar) bytes 13 | 14 | from 15 | sys.schemas sch 16 | inner join 17 | sys.tables tab 18 | on 19 | tab.schema_id = sch.schema_id 20 | and sch.name not in ('dbo', 'sys') 21 | inner join 22 | sys.columns col 23 | on col.object_id = tab.object_id 24 | inner join 25 | sys.types typ 26 | on 27 | typ.system_type_id = col.system_type_id 28 | and typ.user_type_id = col.user_type_id 29 | left outer join 30 | sys.extended_properties ep 31 | on ep.major_id = tab.object_id and ep.minor_id = col.column_id 32 | union all 33 | select '[' + sch.name + '].[' + tab.name + ']', isnull(ep.value, ''), 0, tab.object_id, '', '', '', '' 34 | from 35 | sys.schemas sch 36 | inner join 37 | sys.tables tab 38 | on 39 | tab.schema_id = sch.schema_id 40 | and sch.name not in ('dbo', 'sys') 41 | left outer join 42 | sys.extended_properties ep 43 | on ep.major_id = tab.object_id and ep.minor_id = 0) 44 | select [objName],[MS_Description], name, max_length, is_nullable, bytes from allDescr 45 | order by object_id, column_id -------------------------------------------------------------------------------- /SQL Server/audit/DDL Trigger.sql: -------------------------------------------------------------------------------- 1 | -- Create DDL trigger for audit 2 | 3 | create TABLE [dbo].[DatabaseLog]( 4 | [DatabaseLogID] [int] IDENTITY(1,1) NOT NULL, 5 | [PostTime] [datetime] NOT NULL, 6 | [DatabaseUser] [sysname] NOT NULL, 7 | [LoginName] [sysname] NOT NULL, 8 | [Event] [sysname] NOT NULL, 9 | [Schema] [sysname] NULL, 10 | [Object] [sysname] NULL, 11 | [TSQL] [nvarchar](max) NOT NULL, 12 | [XmlEvent] [xml] NOT NULL, 13 | CONSTRAINT [PK_DatabaseLog_DatabaseLogID] PRIMARY KEY CLUSTERED 14 | ( 15 | [DatabaseLogID] ASC 16 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 17 | ) ON [PRIMARY] 18 | 19 | GO 20 | 21 | create TRIGGER [ddlDatabaseTriggerLog] ON DATABASE 22 | FOR DDL_DATABASE_LEVEL_EVENTS AS 23 | BEGIN 24 | SET NOCOUNT ON; 25 | DECLARE @data XML; 26 | DECLARE @schema sysname; 27 | DECLARE @object sysname; 28 | DECLARE @eventType sysname; 29 | SET @data = EVENTDATA(); 30 | SET @eventType = @data.value('(/EVENT_INSTANCE/EventType)[1]', 'sysname'); 31 | SET @schema = @data.value('(/EVENT_INSTANCE/SchemaName)[1]', 'sysname'); 32 | SET @object = @data.value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname') 33 | 34 | INSERT [dbo].[DatabaseLog] 35 | ( 36 | [PostTime], 37 | [DatabaseUser], 38 | [LoginName], 39 | [Event], 40 | [Schema], 41 | [Object], 42 | [TSQL], 43 | [XmlEvent] 44 | ) 45 | VALUES 46 | ( 47 | GETDATE(), 48 | CONVERT(sysname, CURRENT_USER), 49 | @data.value('(/EVENT_INSTANCE/LoginName)[1]', 'sysname'), 50 | @eventType, 51 | CONVERT(sysname, @schema), 52 | CONVERT(sysname, @object), 53 | @data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(max)'), 54 | @data 55 | ); 56 | END; 57 | 58 | GO 59 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Database/02 Create target objects.sql: -------------------------------------------------------------------------------- 1 | USE TargetDB; 2 | GO 3 | /* 4 | Создание типов сообщений 5 | 6 | Указанные имена и свойства типов сообщений должны быть идентичны тем, которые будут 7 | созданы в базе данных InitiatorDB на следующем занятии. 8 | */ 9 | CREATE MESSAGE TYPE [//BothDB/2DBSample/RequestMessage] 10 | VALIDATION = WELL_FORMED_XML; 11 | CREATE MESSAGE TYPE [//BothDB/2DBSample/ReplyMessage] 12 | VALIDATION = WELL_FORMED_XML; 13 | GO 14 | /* 15 | Создание контракта 16 | 17 | Заданное имя и свойства контракта должны быть идентичны имени и свойствам 18 | контракта, который будет создан в базе данных InitiatorDB на следующем занятии. 19 | */ 20 | CREATE CONTRACT [//BothDB/2DBSample/SimpleContract] 21 | ([//BothDB/2DBSample/RequestMessage] 22 | SENT BY INITIATOR, 23 | [//BothDB/2DBSample/ReplyMessage] 24 | SENT BY TARGET 25 | ); 26 | GO 27 | /* 28 | Создание очереди и службы целевой стороны 29 | 30 | Затем запустите его, чтобы создать очередь и службу, которые будут использоваться 31 | для целевой стороны. Инструкция CREATE SERVICE связывает службу с очередью 32 | TargetQueue2DB. Таким образом, все отправляемые службе сообщения помещаются в очередь 33 | TargetQueue2DB. Инструкция CREATE SERVICE также указывает, что только диалоги, 34 | использующие созданный ранее контракт //BothDB/2DBSample/SimpleContract, 35 | могут пользоваться этой службой в качестве целевой. 36 | */ 37 | CREATE QUEUE TargetQueue2DB; 38 | 39 | CREATE SERVICE [//TgtDB/2DBSample/TargetService] 40 | ON QUEUE TargetQueue2DB 41 | ([//BothDB/2DBSample/SimpleContract]); 42 | GO 43 | 44 | -------------------------------------------------------------------------------- /SQL Server/diagnostics/dm_tran_locks details.sql: -------------------------------------------------------------------------------- 1 | select ss.name as sch_name, so.name as obj_name, dt.request_session_id 2 | , db_name = db.name 3 | , hobt_id_desc = isnull(isnull(res.res_name, res_log.res_name), so.name) 4 | , * 5 | from sys.dm_tran_locks dt 6 | left join sys.objects so ON so.object_id = dt.resource_associated_entity_id 7 | left join sys.schemas ss ON ss.schema_id = so.schema_id 8 | left join sys.databases db on db.database_id = dt.resource_database_id 9 | OUTER APPLY ( 10 | SELECT TOP 1 isnull(ss.name, '*') + '.' + isnull(o.name, '*') + '-' + isnull(i.name, '*') as res_name 11 | FROM sys.partitions p 12 | INNER JOIN sys.objects o ON p.object_id = o.object_id 13 | INNER JOIN sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id 14 | INNER JOIN sys.schemas ss ON ss.schema_id = o.schema_id 15 | WHERE p.hobt_id = dt.resource_associated_entity_id 16 | ) res 17 | OUTER APPLY (SELECT TOP 1 isnull(ss.name, '*') + '.' + isnull(o.name, '*') + '-' + isnull(i.name, '*') as res_name 18 | FROM ADFrontLogs.sys.partitions p 19 | INNER JOIN ADFrontLogs.sys.objects o ON p.object_id = o.object_id 20 | INNER JOIN ADFrontLogs.sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id 21 | INNER JOIN ADFrontLogs.sys.schemas ss ON ss.schema_id = o.schema_id 22 | WHERE p.hobt_id = dt.resource_associated_entity_id) res_log 23 | 24 | where dt.request_session_id in (102, 308, 150) --where dt.request_session_id in (102) --where dt.request_session_id in (308) --where dt.request_session_id in (150) 25 | and dt.resource_database_id > 4 26 | and dt.resource_lock_partition = 6 27 | --and dt.request_status <> 'GRANT' 28 | --and so.type_desc IS NOT NULL 29 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Instance/05 Receive request and send responce.sql: -------------------------------------------------------------------------------- 1 | 2 | USE InstTargetDB; 3 | GO 4 | 5 | /* 6 | Получение запроса и отправка ответа 7 | 8 | Получение ответного сообщения из очереди InstTargetQueue и отправку ответного сообщения обратно инициатору. 9 | Инструкция RECEIVE получает сообщение-запрос. Затем следующая инструкция SELECT выводит текст, позволяющий 10 | убедиться, что получено то же сообщение, что было отправлено на предыдущем шаге. Инструкция IF проверяет, 11 | имеет ли полученное сообщение тип запроса и используется ли инструкция SEND для отправки ответного сообщения 12 | инициирующей стороне. Инструкция END CONVERSATION используется для завершения работы целевой стороны диалога. 13 | Последняя инструкция SELECT выводит текст ответного сообщения. 14 | */ 15 | DECLARE @RecvReqDlgHandle UNIQUEIDENTIFIER; 16 | DECLARE @RecvReqMsg NVARCHAR(100); 17 | DECLARE @RecvReqMsgName sysname; 18 | 19 | BEGIN TRANSACTION; 20 | 21 | WAITFOR 22 | ( RECEIVE TOP(1) 23 | @RecvReqDlgHandle = conversation_handle, 24 | @RecvReqMsg = message_body, 25 | @RecvReqMsgName = message_type_name 26 | FROM InstTargetQueue 27 | ), TIMEOUT 1000; 28 | 29 | SELECT @RecvReqMsg AS ReceivedRequestMsg; 30 | 31 | IF @RecvReqMsgName = N'//BothDB/2InstSample/RequestMessage' 32 | BEGIN 33 | DECLARE @ReplyMsg NVARCHAR(100); 34 | SELECT @ReplyMsg = 35 | N'Message for Initiator service.'; 36 | 37 | SEND ON CONVERSATION @RecvReqDlgHandle 38 | MESSAGE TYPE [//BothDB/2InstSample/ReplyMessage] 39 | (@ReplyMsg); 40 | 41 | END CONVERSATION @RecvReqDlgHandle; 42 | END 43 | 44 | SELECT @ReplyMsg AS SentReplyMsg; 45 | 46 | COMMIT TRANSACTION; 47 | GO 48 | 49 | /* 50 | SELECT * 51 | FROM [dbo].[InstTargetQueue] 52 | 53 | SELECT * 54 | FROM sys.transmission_queue 55 | */ -------------------------------------------------------------------------------- /SQL Server/clr/compress/DataCompression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using System.Data.SqlClient; 4 | using System.Data.SqlTypes; 5 | using Microsoft.SqlServer.Server; 6 | using System.IO; 7 | using System.IO.Compression; 8 | 9 | public class DataCompression 10 | { 11 | [SqlFunction(IsDeterministic=true,DataAccess=DataAccessKind.None)] 12 | public static SqlBytes fnCompress(SqlBytes blob) 13 | { 14 | if (blob.IsNull) 15 | return blob; 16 | 17 | byte[] blobData = blob.Buffer; 18 | 19 | MemoryStream compressData = new MemoryStream(); 20 | DeflateStream compressor = new DeflateStream(compressData, CompressionMode.Compress, true); 21 | 22 | compressor.Write(blobData, 0, blobData.Length); 23 | compressor.Flush(); 24 | compressor.Close(); 25 | compressor = null; 26 | 27 | return new SqlBytes(compressData); 28 | } 29 | 30 | [SqlFunction(IsDeterministic=true,DataAccess=DataAccessKind.None)] 31 | public static SqlBytes fnDecompress(SqlBytes compressBlob) 32 | { 33 | if (compressBlob.IsNull) 34 | return compressBlob; 35 | 36 | DeflateStream decompressor = new DeflateStream(compressBlob.Stream, CompressionMode.Decompress, true); 37 | int bytesRead = 1; 38 | int chunkSize = 8192; 39 | byte[] chunk = new byte[chunkSize]; 40 | 41 | MemoryStream decompressData = new MemoryStream(); 42 | try 43 | { 44 | while ((bytesRead = decompressor.Read(chunk, 0, chunkSize)) > 0) 45 | { 46 | decompressData.Write(chunk, 0, bytesRead); 47 | } 48 | } 49 | finally 50 | { 51 | decompressor.Close(); 52 | } 53 | return new SqlBytes(decompressData); 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SQL Server/jobs/cross jobs.sql: -------------------------------------------------------------------------------- 1 | -- Показывает задания, которые пересекаются по времени выполнения 2 | use [msdb] 3 | GO 4 | with ste as( 5 | select 6 | jh.job_id, 7 | jh.step_id, 8 | convert(datetime,cast(jh.run_date as varchar(8)),112)+CONVERT(datetime,Tfull.T,108) as run_datetime, 9 | convert(datetime,cast(jh.run_date as varchar(8)),112)+CONVERT(datetime,Tfull.T,108)+CONVERT(datetime,Tdfull.T,108) as end_datetime, 10 | CONVERT(datetime,Tdfull.T,108) as duration 11 | from dbo.sysjobhistory as jh 12 | cross apply(select T = right('00000'+cast(jh.run_time as varchar(6)),6))T 13 | cross apply(select T = substring(T.T,1,2))Th 14 | cross apply(select T = substring(T.T,3,2))Tm 15 | cross apply(select T = substring(T.T,5,2))Ts 16 | cross apply(select T = Th.T+':'+Tm.T+':'+Ts.T)Tfull 17 | cross apply(select T = right('00000'+cast(jh.run_duration as varchar(6)),6))Td 18 | cross apply(select T = substring(Td.T,1,2))Tdh 19 | cross apply(select T = substring(Td.T,3,2))Tdm 20 | cross apply(select T = substring(Td.T,5,2))Tds 21 | cross apply(select T = Tdh.T+':'+Tdm.T+':'+Tds.T)Tdfull 22 | 23 | where jh.run_status = 1 24 | and jh.step_id = 0 25 | ) 26 | SELECT ROW_NUMBER() over (partition by convert(varchar,a.run_datetime,112) order by a.run_datetime) as row_num, 27 | j.name as job_a, 28 | a.step_id as job_a_step_id, 29 | a.run_datetime as job_a_runtime, 30 | a.end_datetime as job_a_endtime, 31 | a.duration as job_a_duration, 32 | j0.name as job_b, 33 | a0.step_id as job_b_step_id, 34 | a0.run_datetime as job_b_runtime, 35 | a0.end_datetime as job_b_endtime, 36 | a0.duration as job_b_duration, 37 | a.job_id as job_a_id, 38 | a0.job_id as job_b_id 39 | FROM ste as a 40 | JOIN ste as a0 ON a.job_id <> a0.job_id 41 | join dbo.sysjobs as j on j.job_id = a.job_id 42 | join dbo.sysjobs as j0 on j0.job_id = a0.job_id 43 | AND a0.end_datetime >= a.run_datetime 44 | AND a.end_datetime >= a0.run_datetime 45 | GO 46 | -------------------------------------------------------------------------------- /SQL Server/clr/invalid_objects/readme.txt: -------------------------------------------------------------------------------- 1 | [Info] 2 | This function return null if object is valid or return error message. 3 | 4 | [Install] 5 | USE [master] 6 | GO 7 | sp_configure 'clr enabled',1 8 | GO 9 | reconfigure with override 10 | GO 11 | alter database [test] set trustworthy on 12 | GO 13 | use [test] 14 | GO 15 | 16 | Create assembly [InvalidObjects] 17 | from 'c:\SQL\clr\InvalidObject.dll' 18 | WITH PERMISSION_SET = external_access; 19 | GO 20 | 21 | Create function dbo.GetInvalidObjectInfo(@object_id int,@dbName sysname,@serverName sysname=null) 22 | returns nvarchar(max) 23 | AS EXTERNAL NAME InvalidObjects.InvalidObjects.GetInvalidObjectInfo 24 | GO 25 | 26 | [Samples] 27 | -- This script to use for find invalid object ib database. 28 | select 29 | cast(schemaname as varchar(32)) [schema], 30 | cast (name as varchar(64)) name, 31 | cast(type as varchar(12)) as [type], 32 | err 33 | ,'alter schema ['+schemaname+'_old] transfer '+quotename(schemaname)+'.'+quotename(name) as script -- script from transfer object to another schema. 34 | from 35 | (select schema_name(schema_id) as schemaname,name,type,dbo.GetInvalidObjectInfo(object_id,db_name(),null) as err 36 | from sys.all_objects 37 | where [type] in ('V','P','FN','TF','IF') -- Object type for scan 38 | and name not like 'MSmerge_%' collate Cyrillic_General_CS_AS -- Exclude replica object (case sensivity) 39 | and name not like 'sp_MSsync_%' collate Cyrillic_General_CS_AS -- Exclude replica object (case sensivity) 40 | and name not like 'sp_MScft_%' collate Cyrillic_General_CS_AS -- Exclude replica object (case sensivity) 41 | and schema_name(schema_id) not in ('sys') -- Exclude schema for scaning 42 | )t 43 | where 44 | t.err is not null and -- Show only invalid object 45 | t.err not like 'Invalid object name ''#%' and -- Exclude object with error like mask. 46 | schemaname not like '%old' -- exclude schema to transfer object 47 | order by 1,2 48 | GO -------------------------------------------------------------------------------- /SQL Server/diagnostics/show space db.sql: -------------------------------------------------------------------------------- 1 | /* 2 | DBCC SHRINKFILE(2,500) 3 | GO 4 | */ 5 | ; 6 | WITH spaceused as( 7 | select 8 | a.FILEID, 9 | [FILE_SIZE_MB] = 10 | convert(decimal(12,3),round(a.size/128.000,3)), 11 | [SPACE_USED_MB] = 12 | convert(decimal(12,3),round(fileproperty(a.name,'SpaceUsed')/128.000,3)), 13 | [FREE_SPACE_MB] = 14 | convert(decimal(12,3),round((a.size-fileproperty(a.name,'SpaceUsed'))/128.000,3)) , 15 | [GROWTH_MB] = convert(decimal(12,3),round(a.growth/128.000,3)), 16 | NAME = left(a.NAME,128), 17 | FILENAME = left(a.FILENAME,520), 18 | FILE_GROUP = fg.name, 19 | STATE_DESC = df.state_desc, 20 | [DEFAULT] = fg.is_default 21 | from 22 | sys.sysfiles a 23 | left join sys.database_files df on df.file_id = a.fileid 24 | left join sys.filegroups as fg on fg.data_space_id = df.data_space_id 25 | ) 26 | select 27 | FILEID, 28 | FILE_SIZE_MB, 29 | SPACE_USED_MB, 30 | CAST(((spaceused.SPACE_USED_MB*1.0)/spaceused.FILE_SIZE_MB)*100 AS DECIMAL(5,2)) AS UsePercent, 31 | FREE_SPACE_MB, 32 | CAST(((spaceused.FREE_SPACE_MB*1.0)/spaceused.FILE_SIZE_MB)*100 AS DECIMAL(5,2)) AS FreePercent, 33 | [GROWTH_MB], 34 | [NAME], 35 | [FILENAME], 36 | FILE_GROUP, 37 | [STATE_DESC], 38 | [DEFAULT], 39 | 'DBCC SHRINKFILE('+cast(FILEID as varchar) + ','+cast(cast(SPACE_USED_MB as int)+5 as varchar)+') 40 | GO 41 | ' as ExecShrink 42 | from spaceused 43 | union all 44 | select 45 | NULL as FILEID, 46 | sum(FILE_SIZE_MB)as FILE_SIZE_MB, 47 | sum(SPACE_USED_MB)as SPACE_USED_MB, 48 | CAST(AVG(((spaceused.SPACE_USED_MB*1.0)/spaceused.FILE_SIZE_MB)*100) AS DECIMAL(5,2)) AS UsePercent, 49 | sum(FREE_SPACE_MB)as FREE_SPACE_MB, 50 | CAST(AVG(((spaceused.FREE_SPACE_MB*1.0)/spaceused.FILE_SIZE_MB)*100) AS DECIMAL(5,2)) AS UsePercent, 51 | null, 52 | NULL as [NAME], 53 | NULL as [FILENAME], 54 | 'ONLINE' as [STATE_DESC], 55 | NULL as FILE_GROUP, 56 | NULL as [DEFAULT], 57 | NULL 58 | from spaceused 59 | ORDER BY [DEFAULT]DESC ,FILE_GROUP,FILEID 60 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Single Database/00 introduce.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Обзор учебника 3 | 4 | Этот учебник показывает, как создавать объекты баз данных, необходимые для поддержания 5 | простого диалога Service Broker «запрос-ответ». Далее предстоит начать диалог и в рамках 6 | этого диалога передавать сообщения. 7 | 8 | В каждом диалоге Service Broker есть два участника: инициатор диалога и его цель. На 9 | этом занятии будут выполняться следующие задачи. 10 | >Создание службы и очереди для целевой стороны, а также службы и очереди для инициатора 11 | диалога. 12 | >Создание типа сообщения-запроса и типа сообщения-ответа. 13 | >Создание контракта, в котором указывается, что сообщения-запросы передаются от инициатора 14 | к цели, а сообщения-ответы — от цели к инициатору. 15 | 16 | Далее будет проведен простой диалог. 17 | >Начните диалог. 18 | >Направьте запрос от инициатора к цели. 19 | >Получите запрос на целевой стороне и направьте ответ инициатору. 20 | >Получите ответ на стороне инициатора. 21 | >Завершите диалог. 22 | 23 | Сообщения не передаются по сети для диалогов, обе конечные точки которых принадлежат одному 24 | экземпляру компонента Database Engine. Система безопасности компонента Database Engine и 25 | заданные разрешения ограничивают доступ авторизованными участниками. Для этого сценария не 26 | требуется шифрование сети. 27 | 28 | Учебник разделен на три занятия. 29 | 30 | Занятие 1. Создание объектов диалога 31 | На этом занятии выполняется создание типов сообщений, контрактов, служб и очередей, 32 | необходимых для поддержки простых диалогов Service Broker. 33 | 34 | Занятие 2. Начало диалога и передача сообщений 35 | На этом занятии устанавливается простой диалог; в рамках этого процесса диалог создается, 36 | а затем отправляется сообщение-запрос от инициатора к цели. Затем передается сообщение-ответ 37 | инициатору, и диалог завершается. 38 | 39 | Занятие 3. Удаление объектов диалога 40 | На этом занятии удаляются объекты, созданные для поддержки диалога. 41 | */ -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Instance/03 Continue TargetInst.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Создание ссылок на объекты инициатора 3 | 4 | Измените предложение FROM FILE таким образом, чтобы оно указывало на папку, в которую скопирован 5 | файл InstInitiatorCertficate.cer в шаге 4 на занятии 2. Затем выполните этот код, чтобы создать 6 | учетную запись пользователя инициатора и поместить в нее целевой сертификат. 7 | */ 8 | USE InstTargetDB 9 | GO 10 | CREATE USER InitiatorUser WITHOUT LOGIN; 11 | 12 | CREATE CERTIFICATE InstInitiatorCertificate 13 | AUTHORIZATION InitiatorUser 14 | FROM FILE = 15 | N'C:\SQL\InstInitiatorCertificate.cer'; 16 | GO 17 | 18 | /* 19 | Создание маршрутов 20 | 21 | Вместо строки MyInitiatorComputer укажите имя компьютера, на котором выполняется 22 | экземпляр инициатора. Затем выполните код для создания маршрутов к целевой службе 23 | и службе инициатора, а также привязки удаленной службы, связывающей InitiatorUser 24 | с маршрутом службы инициатора. 25 | 26 | В следующих инструкциях CREATE ROUTE предполагается, что в целевом экземпляре 27 | отсутствуют повторяющиеся имена служб. Если на целевом экземпляре в нескольких 28 | базах данных имеются службы с одинаковым именем, укажите в предложении BROKER_INSTANCE 29 | базу данных, для которой нужно открыть диалог. 30 | */ 31 | DECLARE @Cmd NVARCHAR(4000); 32 | 33 | SET @Cmd = N'USE InstTargetDB; 34 | CREATE ROUTE InstInitiatorRoute 35 | WITH SERVICE_NAME = 36 | N''//InstDB/2InstSample/InitiatorService'', 37 | ADDRESS = N''TCP://SR-SQL-01:4022'';'; 38 | 39 | EXEC (@Cmd); 40 | 41 | SET @Cmd = N'USE msdb 42 | CREATE ROUTE InstTargetRoute 43 | WITH SERVICE_NAME = 44 | N''//TgtDB/2InstSample/TargetService'', 45 | ADDRESS = N''LOCAL'''; 46 | 47 | EXEC (@Cmd); 48 | GO 49 | GRANT SEND 50 | ON SERVICE::[//TgtDB/2InstSample/TargetService] 51 | TO InitiatorUser; 52 | GO 53 | CREATE REMOTE SERVICE BINDING InitiatorBinding 54 | TO SERVICE N'//InstDB/2InstSample/InitiatorService' 55 | WITH USER = InitiatorUser; 56 | GO 57 | -------------------------------------------------------------------------------- /SQL Server/extended event/AuditChanges.sql: -------------------------------------------------------------------------------- 1 | create event session [AuditChanges] on server 2 | add event sqlserver.object_altered(set collect_database_name=(1) 3 | action(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.is_system,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_nt_username,sqlserver.session_server_principal_name,sqlserver.sql_text) 4 | where ([package0].[not_equal_uint64]([database_id],(2)) and [package0].[not_equal_binary_data]([sqlserver].[server_principal_sid],0x0105000000000005150000000848146EDD64B6535259C1170C040000) and [object_type]<>(21587))), 5 | add event sqlserver.object_created(set collect_database_name=(1) 6 | action(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.is_system,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_nt_username,sqlserver.session_server_principal_name,sqlserver.sql_text) 7 | where ([package0].[not_equal_uint64]([database_id],(2)) and [package0].[not_equal_binary_data]([sqlserver].[server_principal_sid],0x0105000000000005150000000848146EDD64B6535259C1170C040000) and [object_type]<>(21587))), 8 | add event sqlserver.object_deleted(set collect_database_name=(1) 9 | action(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.is_system,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_nt_username,sqlserver.session_server_principal_name,sqlserver.sql_text) 10 | where ([package0].[not_equal_uint64]([database_id],(2)) and [package0].[not_equal_binary_data]([sqlserver].[server_principal_sid],0x0105000000000005150000000848146EDD64B6535259C1170C040000) and [object_type]<>(21587))) 11 | add target package0.event_file(set filename=N'D:\MSSQL\Audit\AuditChanges',max_file_size=(1000),max_rollover_files=(25)) 12 | with (max_memory=102400 kb,event_retention_mode=allow_multiple_event_loss,max_dispatch_latency=60 seconds,max_event_size=0 kb,memory_partition_mode=per_node,track_causality=on,startup_state=on) 13 | go 14 | 15 | 16 | -------------------------------------------------------------------------------- /SQL Server/Service Broker/transmission queue.sql: -------------------------------------------------------------------------------- 1 | SELECT far_service,far_broker_instance,COUNT(*) 2 | FROM sys.conversation_endpoints 3 | GROUP BY far_service , 4 | far_broker_instance 5 | ORDER BY far_service 6 | 7 | select p.[rows] as [XmitQ Depth] 8 | FROM sys.objects as o JOIN sys.partitions AS p 9 | ON p.object_id = o.object_id 10 | WHERE o.name = 'sysxmitqueue' 11 | 12 | SELECT TOP 1 dateadd(hour, 3, enqueue_time) as enqueue_time2,conversation_handle , 13 | to_service_name , 14 | to_broker_instance , 15 | from_service_name , 16 | service_contract_name , 17 | enqueue_time , 18 | message_sequence_number , 19 | message_type_name , 20 | is_conversation_error , 21 | is_end_of_dialog , 22 | message_body , 23 | transmission_status , 24 | priority 25 | FROM [sys].[transmission_queue] WITH (NOLOCK) 26 | ORDER BY enqueue_time2 asc 27 | 28 | 29 | -- спирт по закрытию. 30 | SELECT 'END CONVERSATION '''+CONVERT(VARCHAR(36),conversation_handle)+''' WITH CLEANUP 31 | GO 32 | ' 33 | FROM sys.conversation_endpoints 34 | WHERE --state_desc = 'DISCONNECTED_OUTBOUND' 35 | far_service = 'http://alfa-direct.ru/SQL/_Queue/accounts_TargetService_POSTTRADEFOND' 36 | 37 | -- чистка дополнительных таблиц 38 | SELECT COUNT(*) 39 | --DELETE sc 40 | FROM accounts.SessionConversations sc 41 | LEFT JOIN sys.conversation_endpoints ce 42 | ON ce.conversation_handle = sc.Handle 43 | WHERE ce.conversation_handle IS NULL 44 | -- чистка дополнительных таблиц 45 | -------------------------------------------------------------------------------- /SQL Server/diagnostics/FindObjects.sql: -------------------------------------------------------------------------------- 1 | -- Поиск объекта в БД 2 | DECLARE @FindText SYSNAME = '%Ankets%Notify%' 3 | 4 | -- Поиск в объектах БД 5 | SELECT 'Objects' AS Obj,OBJECT_SCHEMA_NAME(ao.object_id) AS SchemaName,ao.name AS ObjectName,ao.type_desc,sm.definition 6 | FROM sys.all_objects ao 7 | LEFT JOIN sys.sql_modules sm 8 | ON sm.object_id = ao.object_id 9 | WHERE ao.name LIKE @FindText 10 | OR sm.definition LIKE @FindText 11 | 12 | -- Поиск в зависимостях 13 | SELECT 'Dependence' AS Obj,do.type_desc as DObjType,OBJECT_SCHEMA_NAME(do.object_id)+'.'+OBJECT_NAME(do.object_id) AS DependObject,ro.type_desc as RObjType,OBJECT_SCHEMA_NAME(ro.object_id)+'.'+OBJECT_NAME(ro.object_id) AS ReferenceObj 14 | FROM sys.sql_dependencies sd 15 | INNER JOIN sys.all_objects do 16 | ON sd.object_id = do.object_id 17 | INNER JOIN sys.all_objects ro 18 | ON ro.object_id = sd.referenced_major_id 19 | WHERE 20 | OBJECT_NAME(sd.object_id) LIKE @FindText 21 | OR OBJECT_NAME(sd.referenced_major_id) LIKE @FindText 22 | 23 | -- поиск в синонимах имя или ссылка на объект 24 | SELECT 'Synonyms' AS Obj,OBJECT_SCHEMA_NAME(s.object_id) AS SchemaName,name as ObjectName,s.base_object_name 25 | FROM sys.synonyms s 26 | WHERE name LIKE @FindText 27 | OR s.base_object_name LIKE @FindText 28 | 29 | -- Поиск в линкед серверах 30 | SELECT 'LinkedServers' AS Obj, s.server_id,s.name,s.data_source 31 | FROM sys.servers s 32 | WHERE name LIKE @FindText 33 | OR s.data_source LIKE @FindText 34 | 35 | -- ServiceBroker 36 | SELECT 'SB_QUEUE' AS Obj,name 37 | FROM sys.service_message_types smt 38 | WHERE smt.name LIKE @FindText 39 | 40 | SELECT 'SB_CONTRACT' AS Obj,name 41 | FROM sys.service_contracts sc 42 | WHERE sc.name LIKE @FindText 43 | 44 | SELECT 'SB_SERVICE' AS Obj,OBJECT_SCHEMA_NAME(s.object_id) AS SchemaName,name as ObjectName,s.activation_procedure 45 | FROM sys.service_queues s 46 | WHERE s.name LIKE @FindText 47 | OR s.activation_procedure LIKE @FindText 48 | 49 | SELECT 'SB_SERVICE' AS Obj,name 50 | FROM sys.services s 51 | WHERE s.name LIKE @FindText 52 | 53 | SELECT 'SB_ROUTES' AS Obj, r.name, 54 | r.remote_service_name, 55 | r.address 56 | FROM sys.routes r 57 | WHERE 58 | r.name LIKE @FindText 59 | OR r.remote_service_name LIKE @FindText 60 | OR r.address LIKE @FindText 61 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Instance/00 introduce.sql: -------------------------------------------------------------------------------- 1 | /*. 2 | Этот учебник построен на основе задач, рассмотренных в учебнике Завершение диалога между базами данных. 3 | В настоящем учебнике показан порядок настройки диалога для запуска его между двумя экземплярами компонента 4 | Database Engine. 5 | 6 | В нем используются практически те же шаги, что в учебнике «Завершение диалога между двумя базами данных», 7 | за исключением следующих моментов. 8 | >Обе базы данных размещены в разных экземплярах компонента Database Engine. 9 | >Показано, как создавать конечные точки компонента Service Broker и маршруты 10 | для установления сетевых подключений между двумя экземплярами. 11 | >В предыдущих учебниках передача сообщений по сети не рассматривалась. Поэтому 12 | для обеспечения защиты сообщений от несанкционированного доступа в них использовались 13 | разрешения компонента Database Engine. На занятии 3 показано, как создавать сертификаты 14 | и привязки удаленных служб для шифрования сетевых сообщений. 15 | 16 | В этом учебнике экземпляр компонента Database Engine, содержащий базу данных инициатора, называется «экземпляром инициатора». 17 | Экземпляр, содержащий целевую базу данных, называется «целевым экземпляром». 18 | 19 | Учебник состоит из шести занятий. 20 | 21 | Занятие 1. Создание целевой базы данных 22 | На этом занятии создается целевая база данных и все объекты, не имеющие зависимостей в базе данных инициатора: 23 | конечная точка, главный ключ, сертификат, пользователи, типы сообщений, контракт, служба и очередь. 24 | 25 | Занятие 2. Создание инициирующей базы данных 26 | На этом занятии создается база данных инициатора и ее конечная точка, главный ключ, сертификат, пользователи, 27 | маршруты, привязки удаленных служб, типы сообщений, контракт, служба и очередь. 28 | 29 | Занятие 3. Завершение объектов целевой стороны диалога 30 | На этом занятии создаются целевые объекты, имеющие зависимости в базе данных инициатора: сертификаты, пользователи, 31 | маршруты и привязки удаленных служб. 32 | 33 | Занятие 4. Начало диалога 34 | На этом занятии рассматривается запуск диалога и отправка сообщения запроса с экземпляра инициатора на целевой экземпляр. 35 | 36 | Занятие 5. Получение запроса и отправка ответа 37 | На этом занятии целевая служба получает сообщение запроса и отправляет ответное сообщение инициатору. 38 | 39 | Занятие 6. Получение ответа и завершение диалога 40 | На этом занятии вызывающая служба получает ответное сообщение и завершает диалог. 41 | */ -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Database/00 introduce.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Обзор учебника 3 | 4 | Материал этого учебника построен на задачах, которые вы освоили в учебнике Завершение 5 | диалога в пределах одной базы данных. В этом учебнике объясняется, как настраивать диалог 6 | таким образом, чтобы он выполнялся между двумя базами данных на одном и том же экземпляре 7 | компонента Database Engine. 8 | 9 | Этапы, описанные в занятии 2, аналогичны этапам, изложенным в занятии 1, со следующими исключениями. 10 | 11 | >Предстоит создать две базы данных: InitiatorDB и TargetDB. Будут созданы как инициирующие служба 12 | и очередь в базе данных InitiatorDB, так и целевые служба и очередь в базе данных TargetDB. 13 | 14 | >Будут созданы две копии типов сообщений и контактов, одна в базе данных InitiatorDB, а другая — 15 | в базе данных TargetDB. Обе стороны диалога должны иметь доступ к типу сообщений и к определениям 16 | контрактов, являющимся идентичными. 17 | 18 | >В базе данных InitiatorDB свойству TRUSTWORTHY должно быть задано значение ON. Это самый простой 19 | способ активизации диалога между двумя базами данных, размещенными на одном и том же экземпляре 20 | компонента Database Engine. 21 | 22 | >Вы узнаете о том, какие инструкции нужно выполнять в каждой базе данных для завершения диалога, 23 | а также о порядке, в котором они должны следовать. 24 | 25 | Сообщения не передаются по сети для диалогов, обе конечные точки которых принадлежат одному экземпляру 26 | компонента Database Engine. Система безопасности компонента Database Engine и заданные разрешения 27 | ограничивают доступ авторизованными участниками. Для этого сценария не требуется шифрование сети. 28 | 29 | Учебник разделен на четыре занятия. 30 | 31 | Занятие 1. Создание баз данных 32 | На этом занятии будут созданы базы данных и включен параметр TRUSTWORTHY в инициирующей диалог базе данных. 33 | 34 | Занятие 2. Создание объектов целевой стороны диалога 35 | На этом занятии будут созданы типы сообщений, контракты, службы и очереди в целевой базе данных. 36 | 37 | Занятие 3. Создание объектов инициирующей стороны диалога 38 | На этом занятии будут созданы типы сообщений, контракты, службы и очереди в инициирующей базе данных. 39 | 40 | Занятие 4. Начало диалога и передача сообщений 41 | На этом занятии будет выполнен простой диалог; в рамках этого процесса диалог создается, а затем 42 | отправляется сообщение-запрос от инициатора к цели. После этого передается сообщение-ответ инициатору 43 | и выполняется завершение диалога. 44 | */ -------------------------------------------------------------------------------- /SQL Server/indexes/index defrag.sql: -------------------------------------------------------------------------------- 1 | -- »щем сильно дефрагментированные индексы и генерируем скрипт по перестройки секций. 2 | WITH v_index AS ( 3 | select 4 | SCHEMA_ID(OBJECT_SCHEMA_NAME(ix.object_id,DB_ID())) as [schema_id], 5 | OBJECT_SCHEMA_NAME(ix.object_id,DB_ID()) as [schema_name], 6 | ix.object_id as [object_id], 7 | OBJECT_NAME(ix.object_id) as [object_name], 8 | ix.index_id as [index_id], 9 | ix.Name as [index_name], 10 | ix.type, 11 | ix.type_desc, 12 | ix.is_unique, 13 | ix.data_space_id, 14 | case ds.type 15 | when 'FG' then ds.name 16 | when 'PS' then (select distinct name from sys.partition_schemes where data_space_id = ix.data_space_id) 17 | end as data_space, 18 | isnull((select fanout from sys.partition_functions prtfn 19 | join sys.partition_schemes as prtsch on prtfn.function_id = prtsch.function_id 20 | where prtsch.data_space_id = ix.data_space_id),0) as part_count, 21 | ix.ignore_dup_key, 22 | ix.is_primary_key, 23 | ix.is_unique_constraint, 24 | ix.fill_factor, 25 | ix.is_padded, 26 | ix.is_disabled, 27 | ix.is_hypothetical, 28 | ix.allow_row_locks, 29 | ix.allow_page_locks, 30 | ix.filter_definition 31 | from sys.indexes as ix 32 | join sys.data_spaces as ds on ds.data_space_id = ix.data_space_id 33 | ) 34 | SELECT 35 | quotename(OBJECT_SCHEMA_NAME(st.object_id,st.database_id)) + '.' + quotename(object_name(st.object_id)) as obj_name, 36 | quotename(i.index_name) as idx_name, 37 | st.avg_fragmentation_in_percent, 38 | i.allow_page_locks, 39 | case ds.type 40 | when 'FG' then ds.name 41 | when 'PS' then (select distinct name from sys.partition_schemes where data_space_id = i.data_space_id) 42 | end as data_space, 43 | i.part_count as part_count, 44 | CASE part_count when 0 then 0 else st.partition_number end as part_number, 45 | st.page_count, 46 | i.[type], 47 | CASE when st.avg_fragmentation_in_percent > 30 48 | then 'ALTER INDEX '+QUOTENAME(i.index_name)+' ON '+QUOTENAME(i.schema_name)+'.'+QUOTENAME(i.object_name)+' REBUILD PARTITION = '+ CASE part_count when 0 then 'ALL' else CAST(st.partition_number AS VARCHAR) end +' 49 | GO 50 | ' 51 | ELSE '' 52 | END AS Script 53 | from v_index i 54 | INNER JOIN sys.data_spaces ds 55 | ON ds.data_space_id = i.data_space_id 56 | join master.sys.dm_db_index_physical_stats(db_id(),null,null,null,'LIMITED') st on st.object_id = i.object_id and st.index_id = i.index_id 57 | where 58 | i.is_disabled = 0 59 | and i.index_id > 1 60 | and st.page_count > 8 61 | and st.page_count <= 1000000000 62 | and st.avg_fragmentation_in_percent >= 50 63 | -------------------------------------------------------------------------------- /SQL Server/generators/create class from table.sql: -------------------------------------------------------------------------------- 1 | declare @ObjectId int; 2 | declare @TableName sysname; 3 | 4 | select 5 | @ObjectId = object_id 6 | ,@TableName = schema_name(schema_id)+'_'+name 7 | from 8 | sys.all_objects 9 | where 10 | name = 'CountryView' 11 | and schema_id = schema_id('mt') 12 | 13 | declare @Result varchar(max) = 'public class ' + @TableName + ' 14 | {' 15 | 16 | select @Result = @Result + ' 17 | public ' + (CASE WHEN ColumnName = 'RowVersion' THEN 'byte[]' ELSE ColumnType END) + NullableSign + ' ' + ColumnName + ' { get; set; } 18 | ' 19 | from 20 | ( 21 | select 22 | replace(col.name, ' ', '_') ColumnName, 23 | column_id ColumnId, 24 | case typ.name 25 | when 'bigint' then 'long' 26 | when 'binary' then 'byte[]' 27 | when 'bit' then 'bool' 28 | when 'char' then 'string' 29 | when 'date' then 'DateTime' 30 | when 'datetime' then 'DateTime' 31 | when 'datetime2' then 'DateTime' 32 | when 'datetimeoffset' then 'DateTimeOffset' 33 | when 'decimal' then 'decimal' 34 | when 'float' then 'float' 35 | when 'image' then 'byte[]' 36 | when 'int' then 'int' 37 | when 'money' then 'decimal' 38 | when 'nchar' then 'string' 39 | when 'ntext' then 'string' 40 | when 'numeric' then 'decimal' 41 | when 'nvarchar' then 'string' 42 | when 'real' then 'double' 43 | when 'smalldatetime' then 'DateTime' 44 | when 'smallint' then 'short' 45 | when 'smallmoney' then 'decimal' 46 | when 'text' then 'string' 47 | when 'time' then 'TimeSpan' 48 | when 'timestamp' then 'timestamp' 49 | when 'rowversion' then 'byte[]' 50 | when 'tinyint' then 'byte' 51 | when 'uniqueidentifier' then 'Guid' 52 | when 'varbinary' then 'byte[]' 53 | when 'varchar' then 'string' 54 | else 'UNKNOWN_' + typ.name 55 | end ColumnType, 56 | case 57 | when col.is_nullable = 1 and typ.name in ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier') 58 | then '?' 59 | else '' 60 | end NullableSign 61 | from sys.columns col 62 | join sys.types typ on 63 | col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id 64 | where 65 | object_id = @ObjectId 66 | ) t 67 | order by ColumnId 68 | 69 | set @Result = @Result + ' 70 | }' 71 | 72 | print @Result -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Single Database/01 Single database.sql: -------------------------------------------------------------------------------- 1 | -- https://msdn.microsoft.com/ru-ru/library/bb839488%28v=sql.105%29.aspx 2 | USE [master] 3 | GO 4 | /* 5 | Создание базы данных 6 | */ 7 | IF NOT EXISTS (SELECT 1 FROM sys.databases WHERE name = 'SingleSSB') 8 | CREATE DATABASE [SingleSSB] 9 | GO 10 | /* 11 | Включение SERVICE BROKER 12 | */ 13 | ALTER DATABASE [SingleSSB] SET ENABLE_BROKER 14 | GO 15 | 16 | USE [SingleSSB] 17 | GO 18 | /* 19 | Создание типов сообщений 20 | 21 | Поскольку на объекты Service Broker часто ссылаются несколько экземпляров компонента Database Engine, 22 | большинству объектов компонента Service Broker присваиваются имена в формате URI. Это помогает обеспечить 23 | уникальность имен в пределах нескольких компьютеров. Оба типа сообщений указывают, что компонент Service 24 | Broker проверяет лишь то, что сообщения являются правильными XML-документами, но не проверяет их 25 | корректность по конкретной схеме. 26 | */ 27 | CREATE MESSAGE TYPE 28 | [//SSBSExample/SingleDB/RequestMessage] 29 | VALIDATION = WELL_FORMED_XML; 30 | CREATE MESSAGE TYPE 31 | [//SSBSExample/SingleDB/ResponceMessage] 32 | VALIDATION = WELL_FORMED_XML; 33 | GO 34 | /* 35 | Создание контракта 36 | 37 | Контракт указывает, что использующие его диалоги должны отправлять сообщения с типом 38 | [//SSBSExample/SingleDB/RequestMessage] от инициатора к цели, а сообщения с типом 39 | [//SSBSExample/SingleDB/ResponceMessage] — от цели к инициатору. 40 | */ 41 | CREATE CONTRACT [//SSBSExample/SingleDB/SingleContract] 42 | ([//SSBSExample/SingleDB/RequestMessage] 43 | SENT BY INITIATOR, 44 | [//SSBSExample/SingleDB/ResponceMessage] 45 | SENT BY TARGET 46 | ); 47 | GO 48 | /* 49 | Создание очереди и службы целевой (target - цель) стороны 50 | 51 | Поскольку ссылки на очереди из одной и той же базы данных напоминают ссылки на 52 | таблицы и представления, очереди имеют такие же имена, что и таблицы и представления. 53 | Инструкция CREATE SERVICE связывает службу с очередью TargetQueue. Поэтому все сообщения, 54 | отправленные службе, будут помещены в очередь TargetQueue. Инструкция CREATE SERVICE 55 | также указывает, что только диалоги, использующие созданный ранее контракт 56 | [//SSBSExample/SingleDB/SingleContract], могут пользоваться этой службой в качестве целевой. 57 | */ 58 | CREATE QUEUE TargetQueue; 59 | 60 | CREATE SERVICE 61 | [//SSBSExample/SingleDB/TargetService] 62 | ON QUEUE TargetQueue 63 | ([//SSBSExample/SingleDB/SingleContract]); 64 | GO 65 | /* 66 | Создание очереди и службы инициирующей стороны 67 | 68 | Поскольку не указано имя контракта, никакие другие службы не могут использовать эту службу в качестве целевой. 69 | */ 70 | 71 | CREATE QUEUE InitiatorQueue; 72 | 73 | CREATE SERVICE 74 | [//SSBSExample/SingleDB/InitiatorService] 75 | ON QUEUE InitiatorQueue; 76 | GO 77 | 78 | -------------------------------------------------------------------------------- /Tutorial/sql_server/MergeTriggerUsage/MergeTriggerUsage/05 Merge.sql: -------------------------------------------------------------------------------- 1 | ;merge dbo.MergeTbl trg 2 | using ( 3 | select 3 as Id,'CCC' FName 4 | )src 5 | on trg.Id = src.Id 6 | when not matched then 7 | insert values (Id,FName); 8 | /* 9 | Trigger for insert rc=1 10 | Trigger for insert i=1 11 | Trigger after insert rc=1 12 | Trigger after insert i=1 13 | Trigger for all rc=1 14 | Trigger for all i=1 15 | Trigger for all d=0 16 | Trigger after all rc=1 17 | Trigger after all i=1 18 | Trigger after all d=0 19 | 20 | (1 row(s) affected) 21 | 22 | */ 23 | 24 | ;merge dbo.MergeTbl trg 25 | using ( 26 | select 3 as Id,'CCC' FName 27 | )src 28 | on trg.Id = src.Id 29 | when matched then update set FName = src.FName 30 | when not matched then 31 | insert values (Id,FName); 32 | /* 33 | Trigger for insert rc=1 34 | Trigger for insert i=0 35 | Trigger after insert rc=1 36 | Trigger after insert i=0 37 | Trigger for all rc=1 38 | Trigger for all i=0 39 | Trigger for all d=0 40 | Trigger after all rc=1 41 | Trigger after all i=0 42 | Trigger after all d=0 43 | Trigger for update rc=1 44 | Trigger for update i=1 45 | Trigger for update d=1 46 | Trigger after update rc=1 47 | Trigger after update i=1 48 | Trigger after update d=1 49 | Trigger for all rc=1 50 | Trigger for all i=1 51 | Trigger for all d=1 52 | Trigger after all rc=1 53 | Trigger after all i=1 54 | Trigger after all d=1 55 | 56 | (1 row(s) affected) 57 | */ 58 | 59 | ;merge dbo.MergeTbl trg 60 | using ( 61 | select 3 as Id,'CCC' FName 62 | union all 63 | select 4 as Id,'DDD' FName 64 | union all 65 | select 12 as Id,'FFF' FName 66 | 67 | )src 68 | on trg.Id = src.Id 69 | when not matched then 70 | insert values (Id,FName); 71 | /* 72 | Trigger for insert rc=2 73 | Trigger for insert i=2 74 | Trigger after insert rc=2 75 | Trigger after insert i=2 76 | Trigger for all rc=2 77 | Trigger for all i=2 78 | Trigger for all d=0 79 | Trigger after all rc=2 80 | Trigger after all i=2 81 | Trigger after all d=0 82 | 83 | (2 row(s) affected) 84 | */ 85 | 86 | ;merge dbo.MergeTbl trg 87 | using ( 88 | select 21 as Id,'CCC' FName 89 | union all 90 | select 4 as Id,'DDD' FName 91 | union all 92 | select 12 as Id,'FFF' FName 93 | 94 | )src 95 | on trg.Id = src.Id 96 | when matched then update set FName = src.FName 97 | when not matched then 98 | insert values (Id,FName); 99 | /* 100 | Trigger for insert rc=3 101 | Trigger for insert i=1 102 | Trigger after insert rc=3 103 | Trigger after insert i=1 104 | Trigger for all rc=3 105 | Trigger for all i=1 106 | Trigger for all d=0 107 | Trigger after all rc=3 108 | Trigger after all i=1 109 | Trigger after all d=0 110 | Trigger for update rc=3 111 | Trigger for update i=2 112 | Trigger for update d=2 113 | Trigger after update rc=3 114 | Trigger after update i=2 115 | Trigger after update d=2 116 | Trigger for all rc=3 117 | Trigger for all i=2 118 | Trigger for all d=2 119 | Trigger after all rc=3 120 | Trigger after all i=2 121 | Trigger after all d=2 122 | 123 | (3 row(s) affected) 124 | */ -------------------------------------------------------------------------------- /Tutorial/sql_server/MergeTriggerUsage/MergeTriggerUsage/MergeTriggerUsage.ssmssqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2016-12-14T13:27:23.9984179+03:00 8 | SQL 9 | (LOCALDB)\MSSQLLocalDB 10 | 11 | Windows Authentication 12 | 13 | 15 14 | 0 15 | NotSpecified 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:(LOCALDB)\MSSQLLocalDB:True 24 | (LOCALDB)\MSSQLLocalDB 25 | 26 | 01 Create Database.sql 27 | 28 | 29 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:(LOCALDB)\MSSQLLocalDB:True 30 | (LOCALDB)\MSSQLLocalDB 31 | 32 | 02 Insert.sql 33 | 34 | 35 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:(LOCALDB)\MSSQLLocalDB:True 36 | (LOCALDB)\MSSQLLocalDB 37 | 38 | 03 Update.sql 39 | 40 | 41 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:(LOCALDB)\MSSQLLocalDB:True 42 | (LOCALDB)\MSSQLLocalDB 43 | 44 | 04 Delete.sql 45 | 46 | 47 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:(LOCALDB)\MSSQLLocalDB:True 48 | (LOCALDB)\MSSQLLocalDB 49 | 50 | 05 Merge.sql 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Single Database/04 Activate procedure.sql: -------------------------------------------------------------------------------- 1 | USE [SingleSSB]; 2 | GO 3 | 4 | /* 5 | Создание внутренней хранимой процедуры активации 6 | 7 | Чтобы создать хранимую процедуру. Выполняемая хранимая процедура продолжает получать сообщения все 8 | время, пока таковые имеются в очереди. Если по истечении времени ожидания ни одного сообщения не 9 | получено, хранимая процедура завершается. Если полученное сообщение содержит запрос, хранимая процедура 10 | возвращает сообщение, содержащее ответ. Если полученное сообщение является сообщением EndDialog, хранимая 11 | процедура завершает целевую сторону диалога. Если полученное сообщение является сообщением Error, 12 | выполняется откат транзакции. 13 | */ 14 | CREATE PROCEDURE TargetActivProc 15 | AS 16 | DECLARE @RecvReqDlgHandle UNIQUEIDENTIFIER; 17 | DECLARE @RecvReqMsg NVARCHAR(100); 18 | DECLARE @RecvReqMsgName sysname; 19 | 20 | WHILE (1=1) 21 | BEGIN 22 | 23 | BEGIN TRANSACTION; 24 | 25 | WAITFOR 26 | ( RECEIVE TOP(1) 27 | @RecvReqDlgHandle = conversation_handle, 28 | @RecvReqMsg = message_body, 29 | @RecvReqMsgName = message_type_name 30 | FROM [dbo].[TargetQueue] 31 | ), TIMEOUT 5000; 32 | 33 | IF (@@ROWCOUNT = 0) 34 | BEGIN 35 | ROLLBACK TRANSACTION; 36 | BREAK; 37 | END 38 | 39 | IF @RecvReqMsgName = 40 | N'[//SSBSExample/SingleDB/RequestMessage]' 41 | BEGIN 42 | DECLARE @ReplyMsg NVARCHAR(100); 43 | SELECT @ReplyMsg = 44 | N'Message for Initiator service.'; 45 | 46 | SEND ON CONVERSATION @RecvReqDlgHandle 47 | MESSAGE TYPE 48 | [//SSBSExample/SingleDB/ResponceMessage] 49 | (@ReplyMsg); 50 | END 51 | ELSE IF @RecvReqMsgName = 52 | N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog' 53 | BEGIN 54 | END CONVERSATION @RecvReqDlgHandle; 55 | END 56 | ELSE IF @RecvReqMsgName = 57 | N'http://schemas.microsoft.com/SQL/ServiceBroker/Error' 58 | BEGIN 59 | END CONVERSATION @RecvReqDlgHandle; 60 | END 61 | 62 | COMMIT TRANSACTION; 63 | 64 | END 65 | GO 66 | /* 67 | Изменение целевой очереди для указания внутренней активации 68 | 69 | Чтобы задать активацию компонентом Service Broker хранимой процедуры TargetActiveProc для 70 | обработки сообщений из очереди TargetQueueIntAct. Компонент Service Broker запускает копию 71 | процедуры TargetActiveProc каждый раз при получении сообщения в очереди TargetQueueIntAct 72 | при условии, что ни одна копия этой процедуры еще не запущена. Компонент Service Broker 73 | запускает дополнительные копии процедуры TargetActiveProc каждый раз, когда уже работающие 74 | копии не успевают обрабатывать входящие сообщения в имеющемся количестве. 75 | */ 76 | ALTER QUEUE dbo.TargetQueue 77 | WITH ACTIVATION 78 | ( STATUS = ON, 79 | PROCEDURE_NAME = TargetActivProc, 80 | MAX_QUEUE_READERS = 10, 81 | EXECUTE AS SELF 82 | ); 83 | GO 84 | 85 | -------------------------------------------------------------------------------- /SQL Server/tunning/options.sql: -------------------------------------------------------------------------------- 1 | -- функции для просмотра опций подключения 2 | Use [master] 3 | Go 4 | 5 | create function dbo.GetOptions(@option int) 6 | returns table as return ( 7 | select 8 | case when (@option & 0x1) > 0 then 1 else 0 end as [DISABLE_DEF_CNST_CHK], 9 | case when (@option & 0x2) > 0 then 1 else 0 end as [IMPLICIT_TRANSACTIONS], 10 | case when (@option & 0x4) > 0 then 1 else 0 end as [CURSOR_CLOSE_ON_COMMIT], 11 | case when (@option & 0x8) > 0 then 1 else 0 end as [ANSI_WARNINGS], 12 | case when (@option & 0x10) > 0 then 1 else 0 end as [ANSI_PADDING], 13 | case when (@option & 0x20) > 0 then 1 else 0 end as [ANSI_NULLS], 14 | case when (@option & 0x40) > 0 then 1 else 0 end as [ARITHABORT], 15 | case when (@option & 0x80) > 0 then 1 else 0 end as [ARITHIGNORE], 16 | case when (@option & 0x100) > 0 then 1 else 0 end as [QUOTED_IDENTIFIER], 17 | case when (@option & 0x200) > 0 then 1 else 0 end as [NOCOUNT], 18 | case when (@option & 0x400) > 0 then 1 else 0 end as [ANSI_NULL_DFLT_ON], 19 | case when (@option & 0x800) > 0 then 1 else 0 end as [ANSI_NULL_DFLT_OFF], 20 | case when (@option & 0x1000) > 0 then 1 else 0 end as [CONCAT_NULL_YIELDS_NULL], 21 | case when (@option & 0x2000) > 0 then 1 else 0 end as [NUMERIC_ROUNDABORT], 22 | case when (@option & 0x4000) > 0 then 1 else 0 end as [XACT_ABORT] 23 | ) 24 | go 25 | create function dbo.GetOptionsList(@option int) 26 | returns table as return ( 27 | select N'DISABLE_DEF_CNST_CHK' as [OPTION], case when (@option & 0x1) > 0 then 1 else 0 end as [VALUE] 28 | union all 29 | select N'IMPLICIT_TRANSACTIONS' as [OPTION], case when (@option & 0x2) > 0 then 1 else 0 end as [VALUE] 30 | union all 31 | select N'CURSOR_CLOSE_ON_COMMIT' as [OPTION], case when (@option & 0x4) > 0 then 1 else 0 end as [VALUE] 32 | union all 33 | select N'ANSI_WARNINGS' as [OPTION], case when (@option & 0x8) > 0 then 1 else 0 end as [VALUE] 34 | union all 35 | select N'ANSI_PADDING' as [OPTION], case when (@option & 0x10) > 0 then 1 else 0 end as [VALUE] 36 | union all 37 | select N'ANSI_NULLS' as [OPTION], case when (@option & 0x20) > 0 then 1 else 0 end as [VALUE] 38 | union all 39 | select N'ARITHABORT' as [OPTION], case when (@option & 0x40) > 0 then 1 else 0 end as [VALUE] 40 | union all 41 | select N'ARITHIGNORE' as [OPTION], case when (@option & 0x80) > 0 then 1 else 0 end as [VALUE] 42 | union all 43 | select N'QUOTED_IDENTIFIER' as [OPTION], case when (@option & 0x100) > 0 then 1 else 0 end as [VALUE] 44 | union all 45 | select N'NOCOUNT' as [OPTION], case when (@option & 0x200) > 0 then 1 else 0 end as [VALUE] 46 | union all 47 | select N'ANSI_NULL_DFLT_ON' as [OPTION], case when (@option & 0x400) > 0 then 1 else 0 end as [VALUE] 48 | union all 49 | select N'ANSI_NULL_DFLT_OFF' as [OPTION], case when (@option & 0x800) > 0 then 1 else 0 end as [VALUE] 50 | union all 51 | select N'CONCAT_NULL_YIELDS_NULL' as [OPTION], case when (@option & 0x1000) > 0 then 1 else 0 end as [VALUE] 52 | union all 53 | select N'NUMERIC_ROUNDABORT' as [OPTION], case when (@option & 0x2000) > 0 then 1 else 0 end as [VALUE] 54 | union all 55 | select N'XACT_ABORT' as [OPTION], case when (@option & 0x4000) > 0 then 1 else 0 end as [VALUE] 56 | ) 57 | go 58 | 59 | select * from master..GetOptions(@@OPTIONS) 60 | go 61 | select * from master..GetOptionsList(@@OPTIONS) 62 | go 63 | -------------------------------------------------------------------------------- /Tutorial/sql_server/MergeTriggerUsage/MergeTriggerUsage/01 Create Database.sql: -------------------------------------------------------------------------------- 1 | create database MergeTriggerSamples 2 | GO 3 | 4 | use [MergeTriggerSamples] 5 | GO 6 | 7 | create table dbo.MergeTbl ( 8 | Id int not null, 9 | FName nvarchar(10) not null, 10 | constraint PK_MergeTbl primary key (Id) 11 | ) 12 | GO 13 | 14 | create trigger trFI_MergeTbl on dbo.MergeTbl 15 | for insert as 16 | begin 17 | declare @rc int, @i int; 18 | set @rc = @@ROWCOUNT; 19 | select @i = count(*) from inserted; 20 | set nocount on; 21 | print 'Trigger for insert rc='+cast(@rc as varchar); 22 | print 'Trigger for insert i='+cast(@i as varchar); 23 | 24 | end 25 | GO 26 | 27 | create trigger trFU_MergeTbl on dbo.MergeTbl 28 | for update as 29 | begin 30 | declare @rc int, @i int,@d int; 31 | set @rc = @@ROWCOUNT; 32 | select @i = count(*) from inserted; 33 | select @d = count(*) from deleted; 34 | set nocount on; 35 | print 'Trigger for update rc='+cast(@rc as varchar); 36 | print 'Trigger for update i='+cast(@i as varchar); 37 | print 'Trigger for update d='+cast(@d as varchar); 38 | 39 | end 40 | GO 41 | 42 | create trigger trFD_MergeTbl on dbo.MergeTbl 43 | for delete as 44 | begin 45 | declare @rc int, @d int; 46 | set @rc = @@ROWCOUNT; 47 | select @d = count(*) from deleted; 48 | set nocount on; 49 | print 'Trigger for deleted rc='+cast(@rc as varchar); 50 | print 'Trigger for deleted d='+cast(@d as varchar); 51 | 52 | end 53 | GO 54 | 55 | create trigger trAI_MergeTbl on dbo.MergeTbl 56 | after insert as 57 | begin 58 | declare @rc int, @i int; 59 | set @rc = @@ROWCOUNT; 60 | select @i = count(*) from inserted; 61 | set nocount on; 62 | print 'Trigger after insert rc='+cast(@rc as varchar); 63 | print 'Trigger after insert i='+cast(@i as varchar); 64 | 65 | end 66 | GO 67 | 68 | create trigger trAU_MergeTbl on dbo.MergeTbl 69 | after update as 70 | begin 71 | declare @rc int, @i int,@d int; 72 | set @rc = @@ROWCOUNT; 73 | select @i = count(*) from inserted; 74 | select @d = count(*) from deleted; 75 | set nocount on; 76 | print 'Trigger after update rc='+cast(@rc as varchar); 77 | print 'Trigger after update i='+cast(@i as varchar); 78 | print 'Trigger after update d='+cast(@d as varchar); 79 | 80 | end 81 | GO 82 | 83 | create trigger trAD_MergeTbl on dbo.MergeTbl 84 | after delete as 85 | begin 86 | declare @rc int, @d int; 87 | set @rc = @@ROWCOUNT; 88 | select @d = count(*) from deleted; 89 | set nocount on; 90 | print 'Trigger after deleted rc='+cast(@rc as varchar); 91 | print 'Trigger after deleted d='+cast(@d as varchar); 92 | 93 | end 94 | GO 95 | 96 | create trigger trFAll_MergeTbl on dbo.MergeTbl 97 | for insert,update,delete as 98 | begin 99 | declare @rc int, @i int,@d int; 100 | set @rc = @@ROWCOUNT; 101 | select @i = count(*) from inserted; 102 | select @d = count(*) from deleted; 103 | set nocount on; 104 | print 'Trigger for all rc='+cast(@rc as varchar); 105 | print 'Trigger for all i='+cast(@i as varchar); 106 | print 'Trigger for all d='+cast(@d as varchar); 107 | 108 | end 109 | GO 110 | 111 | create trigger trAAll_MergeTbl on dbo.MergeTbl 112 | after insert,update,delete as 113 | begin 114 | declare @rc int, @i int,@d int; 115 | set @rc = @@ROWCOUNT; 116 | select @i = count(*) from inserted; 117 | select @d = count(*) from deleted; 118 | set nocount on; 119 | print 'Trigger after all rc='+cast(@rc as varchar); 120 | print 'Trigger after all i='+cast(@i as varchar); 121 | print 'Trigger after all d='+cast(@d as varchar); 122 | end 123 | GO 124 | 125 | -------------------------------------------------------------------------------- /SQL Server/diagnostics/wait stats.sql: -------------------------------------------------------------------------------- 1 | WITH [Waits] AS 2 | (SELECT 3 | [wait_type], 4 | [wait_time_ms] / 1000.0 AS [WaitS], 5 | ([wait_time_ms] - [signal_wait_time_ms]) / 1000.0 AS [ResourceS], 6 | [signal_wait_time_ms] / 1000.0 AS [SignalS], 7 | [waiting_tasks_count] AS [WaitCount], 8 | 100.0 * [wait_time_ms] / SUM ([wait_time_ms]) OVER() AS [Percentage], 9 | ROW_NUMBER() OVER(ORDER BY [wait_time_ms] DESC) AS [RowNum] 10 | FROM sys.dm_os_wait_stats 11 | WHERE [wait_type] NOT IN ( 12 | N'BROKER_EVENTHANDLER', N'BROKER_RECEIVE_WAITFOR', 13 | N'BROKER_TASK_STOP', N'BROKER_TO_FLUSH', 14 | N'BROKER_TRANSMITTER', N'CHECKPOINT_QUEUE', 15 | N'CHKPT', N'CLR_AUTO_EVENT', 16 | N'CLR_MANUAL_EVENT', N'CLR_SEMAPHORE', 17 | N'DBMIRROR_DBM_EVENT', N'DBMIRROR_EVENTS_QUEUE', 18 | N'DBMIRROR_WORKER_QUEUE', N'DBMIRRORING_CMD', 19 | N'DIRTY_PAGE_POLL', N'DISPATCHER_QUEUE_SEMAPHORE', 20 | N'EXECSYNC', N'FSAGENT', 21 | N'FT_IFTS_SCHEDULER_IDLE_WAIT', N'FT_IFTSHC_MUTEX', 22 | N'HADR_CLUSAPI_CALL', N'HADR_FILESTREAM_IOMGR_IOCOMPLETION', 23 | N'HADR_LOGCAPTURE_WAIT', N'HADR_NOTIFICATION_DEQUEUE', 24 | N'HADR_TIMER_TASK', N'HADR_WORK_QUEUE', 25 | N'KSOURCE_WAKEUP', N'LAZYWRITER_SLEEP', 26 | N'LOGMGR_QUEUE', N'ONDEMAND_TASK_QUEUE', 27 | N'PWAIT_ALL_COMPONENTS_INITIALIZED', 28 | N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP', 29 | N'QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP', 30 | N'REQUEST_FOR_DEADLOCK_SEARCH', N'RESOURCE_QUEUE', 31 | N'SERVER_IDLE_CHECK', N'SLEEP_BPOOL_FLUSH', 32 | N'SLEEP_DBSTARTUP', N'SLEEP_DCOMSTARTUP', 33 | N'SLEEP_MASTERDBREADY', N'SLEEP_MASTERMDREADY', 34 | N'SLEEP_MASTERUPGRADED', N'SLEEP_MSDBSTARTUP', 35 | N'SLEEP_SYSTEMTASK', N'SLEEP_TASK', 36 | N'SLEEP_TEMPDBSTARTUP', N'SNI_HTTP_ACCEPT', 37 | N'SP_SERVER_DIAGNOSTICS_SLEEP', N'SQLTRACE_BUFFER_FLUSH', 38 | N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP', 39 | N'SQLTRACE_WAIT_ENTRIES', N'WAIT_FOR_RESULTS', 40 | N'WAITFOR', N'WAITFOR_TASKSHUTDOWN', 41 | N'WAIT_XTP_HOST_WAIT', N'WAIT_XTP_OFFLINE_CKPT_NEW_LOG', 42 | N'WAIT_XTP_CKPT_CLOSE', N'XE_DISPATCHER_JOIN', 43 | N'XE_DISPATCHER_WAIT', N'XE_TIMER_EVENT') 44 | AND [waiting_tasks_count] > 0 45 | ) 46 | SELECT 47 | MAX ([W1].[wait_type]) AS [WaitType], 48 | CAST (MAX ([W1].[WaitS]) AS DECIMAL (16,2)) AS [Wait_S], 49 | CAST (MAX ([W1].[ResourceS]) AS DECIMAL (16,2)) AS [Resource_S], 50 | CAST (MAX ([W1].[SignalS]) AS DECIMAL (16,2)) AS [Signal_S], 51 | MAX ([W1].[WaitCount]) AS [WaitCount], 52 | CAST (MAX ([W1].[Percentage]) AS DECIMAL (5,2)) AS [Percentage], 53 | CAST ((MAX ([W1].[WaitS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgWait_S], 54 | CAST ((MAX ([W1].[ResourceS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgRes_S], 55 | CAST ((MAX ([W1].[SignalS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgSig_S] 56 | FROM [Waits] AS [W1] 57 | INNER JOIN [Waits] AS [W2] 58 | ON [W2].[RowNum] <= [W1].[RowNum] 59 | GROUP BY [W1].[RowNum] 60 | HAVING SUM ([W2].[Percentage]) - MAX ([W1].[Percentage]) < 95; -- percentage threshold 61 | GO 62 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Single Database/Single Database.ssmssqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2015-08-15T15:34:56.4209481+03:00 8 | SQL 9 | 192.168.56.11 10 | sa 11 | SQL 12 | 13 | 15 14 | 0 15 | NotSpecified 16 | 17 | 18 | 19 | 2015-08-17T11:51:09.2680018+03:00 20 | SQL 21 | 192.168.56.12 22 | sa 23 | SQL 24 | master 25 | 15 26 | 0 27 | NotSpecified 28 | Microsoft SQL Server Management Studio - Query 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 00 introduce.sql 39 | 40 | 41 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.11:False:sa 42 | 192.168.56.11 43 | sa 44 | 01 Single database.sql 45 | 46 | 47 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.11:False:sa 48 | 192.168.56.11 49 | sa 50 | 02 Begin dialog and send message.sql 51 | 52 | 53 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.12:False:sa 54 | 192.168.56.12 55 | sa 56 | 03 Drop Objects.sql 57 | 58 | 59 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.11:False:sa 60 | 192.168.56.11 61 | sa 62 | 04 Activate procedure.sql 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Database/Between Database.ssmssqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2015-08-15T16:15:53.3962449+03:00 8 | SQL 9 | 192.168.56.11 10 | sa 11 | SQL 12 | 13 | 15 14 | 0 15 | NotSpecified 16 | 17 | 18 | 19 | 2015-08-17T11:50:55.2190018+03:00 20 | SQL 21 | 192.168.56.12 22 | sa 23 | SQL 24 | 25 | 15 26 | 0 27 | NotSpecified 28 | Microsoft SQL Server Management Studio - Query 29 | 30 | 31 | 32 | 33 | 34 | 35 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.11:False:sa 36 | 192.168.56.11 37 | sa 38 | 00 introduce.sql 39 | 40 | 41 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.12:False:sa 42 | 192.168.56.12 43 | sa 44 | 01 Create databases.sql 45 | 46 | 47 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.12:False:sa 48 | 192.168.56.12 49 | sa 50 | 02 Create target objects.sql 51 | 52 | 53 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.12:False:sa 54 | 192.168.56.12 55 | sa 56 | 03 Create Initiator objects.sql 57 | 58 | 59 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.11:False:sa 60 | 192.168.56.11 61 | sa 62 | 04 Begin dialog and Send message.sql 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Single Database/02 Begin dialog and send message.sql: -------------------------------------------------------------------------------- 1 | USE [SingleSSB] 2 | GO 3 | /* 4 | Начните диалог и отправьте сообщение-запрос 5 | 6 | Этот код необходимо запускать единым блоком, поскольку для передачи дескриптора диалога из инструкции 7 | BEGIN DIALOG в инструкцию SEND используется переменная. Пакет выполняет инструкцию BEGIN DIALOG для 8 | начала диалога. Он формирует сообщение-запрос и затем с помощью дескриптора диалога в инструкции SEND 9 | направляет сообщение-запрос по этому диалогу. Последняя инструкция SELECT выводит текст отправленного сообщения. 10 | */ 11 | 12 | DECLARE @InitDlgHandle UNIQUEIDENTIFIER; 13 | DECLARE @RequestMsg NVARCHAR(100); 14 | 15 | BEGIN TRANSACTION; 16 | 17 | BEGIN DIALOG @InitDlgHandle 18 | FROM SERVICE 19 | [//SSBSExample/SingleDB/InitiatorService] 20 | TO SERVICE 21 | N'//SSBSExample/SingleDB/TargetService' 22 | ON CONTRACT 23 | [//SSBSExample/SingleDB/SingleContract] 24 | WITH 25 | ENCRYPTION = OFF; 26 | 27 | SELECT @RequestMsg = 28 | N'Message for Target service.'; 29 | 30 | SEND ON CONVERSATION @InitDlgHandle 31 | MESSAGE TYPE 32 | [//SSBSExample/SingleDB/RequestMessage] 33 | (@RequestMsg); 34 | 35 | SELECT @RequestMsg AS SentRequestMsg; 36 | 37 | COMMIT TRANSACTION; 38 | GO 39 | 40 | /* 41 | Получение запроса и отправка ответа 42 | 43 | Затем запустите его для получения ответного сообщения от базы данных TargetQueue1DB и направьте 44 | сообщение-ответ обратно инициатору. Инструкция RECEIVE получает сообщение-запрос. Следующая 45 | инструкция SELECT отображает текст, чтобы можно было проверить, является ли он сообщением, 46 | отправленным на последнем шаге. Инструкция IF проверяет, имеет ли полученное сообщение тип запроса 47 | и используется ли инструкция SEND для отправки ответного сообщения инициатору. 48 | Инструкция END CONVERSATION используется для завершения работы целевой стороны диалога. 49 | Последняя инструкция SELECT выводит текст ответного сообщения. 50 | */ 51 | 52 | SELECT * 53 | FROM [dbo].[InitiatorQueue] 54 | 55 | SELECT * 56 | FROM [dbo].[TargetQueue] 57 | 58 | DECLARE @RecvReqDlgHandle UNIQUEIDENTIFIER; 59 | DECLARE @RecvReqMsg NVARCHAR(100); 60 | DECLARE @RecvReqMsgName sysname; 61 | 62 | BEGIN TRANSACTION; 63 | 64 | WAITFOR 65 | ( RECEIVE TOP(1) 66 | @RecvReqDlgHandle = conversation_handle, 67 | @RecvReqMsg = message_body, 68 | @RecvReqMsgName = message_type_name 69 | FROM TargetQueue 70 | ), TIMEOUT 1000; 71 | 72 | SELECT @RecvReqMsg AS ReceivedRequestMsg; 73 | 74 | IF @RecvReqMsgName = 75 | N'//SSBSExample/SingleDB/RequestMessage' 76 | BEGIN 77 | DECLARE @ReplyMsg NVARCHAR(100); 78 | SELECT @ReplyMsg = 79 | N'Im read message/ all right'; 80 | 81 | SEND ON CONVERSATION @RecvReqDlgHandle 82 | MESSAGE TYPE 83 | [//SSBSExample/SingleDB/ResponceMessage] 84 | (@ReplyMsg); 85 | 86 | END CONVERSATION @RecvReqDlgHandle; 87 | END 88 | 89 | SELECT @ReplyMsg AS SentReplyMsg; 90 | 91 | COMMIT TRANSACTION; 92 | GO 93 | 94 | /* 95 | Получение ответа и завершение диалога 96 | 97 | Инструкция RECEIVE получает ответное сообщение из базы данных IInitiatorQueue1DB. 98 | Инструкция END CONVERSATION завершает работу инициирующей стороны диалога. Последняя 99 | инструкция SELECT выводит текст ответного сообщения, что позволяет убедиться в том, 100 | что оно совпадает с сообщением, отправленным на предыдущем шаге. 101 | */ 102 | 103 | DECLARE @RecvReplyMsg NVARCHAR(100); 104 | DECLARE @RecvReplyDlgHandle UNIQUEIDENTIFIER; 105 | 106 | BEGIN TRANSACTION; 107 | 108 | WAITFOR 109 | ( RECEIVE TOP(1) 110 | @RecvReplyDlgHandle = conversation_handle, 111 | @RecvReplyMsg = message_body 112 | FROM InitiatorQueue 113 | ), TIMEOUT 1000; 114 | 115 | END CONVERSATION @RecvReplyDlgHandle; 116 | 117 | SELECT @RecvReplyMsg AS ReceivedReplyMsg; 118 | 119 | COMMIT TRANSACTION; 120 | GO -------------------------------------------------------------------------------- /SQL Server/returns log file space used by all running transactions.sql: -------------------------------------------------------------------------------- 1 | -- This query returns log file space used by all running transactions. 2 | select 3 | SessionTrans.session_id as [SPID], 4 | enlist_count as [Active Requests], 5 | ActiveTrans.transaction_id as [ID], 6 | ActiveTrans.name as [Name], 7 | ActiveTrans.transaction_begin_time as [Start Time], 8 | case transaction_type 9 | when 1 then 'Read/Write' 10 | when 2 then 'Read-Only' 11 | when 3 then 'System' 12 | when 4 then 'Distributed' 13 | else 'Unknown - ' + convert(varchar(20), transaction_type) 14 | end as [Transaction Type], 15 | case transaction_state 16 | when 0 then 'Uninitialized' 17 | when 1 then 'Not Yet Started' 18 | when 2 then 'Active' 19 | when 3 then 'Ended (Read-Only)' 20 | when 4 then 'Committing' 21 | when 5 then 'Prepared' 22 | when 6 then 'Committed' 23 | when 7 then 'Rolling Back' 24 | when 8 then 'Rolled Back' 25 | else 'Unknown - ' + convert(varchar(20), transaction_state) 26 | end as 'State', 27 | case dtc_state 28 | when 0 then NULL 29 | when 1 then 'Active' 30 | when 2 then 'Prepared' 31 | when 3 then 'Committed' 32 | when 4 then 'Aborted' 33 | when 5 then 'Recovered' 34 | else 'Unknown - ' + convert(varchar(20), dtc_state) 35 | end as 'Distributed State', 36 | DB.Name as 'Database', 37 | database_transaction_begin_time as [DB Begin Time], 38 | case database_transaction_type 39 | when 1 then 'Read/Write' 40 | when 2 then 'Read-Only' 41 | when 3 then 'System' 42 | else 'Unknown - ' + convert(varchar(20), database_transaction_type) 43 | end as 'DB Type', 44 | case database_transaction_state 45 | when 1 then 'Uninitialized' 46 | when 3 then 'No Log Records' 47 | when 4 then 'Log Records' 48 | when 5 then 'Prepared' 49 | when 10 then 'Committed' 50 | when 11 then 'Rolled Back' 51 | when 12 then 'Committing' 52 | else 'Unknown - ' + convert(varchar(20), database_transaction_state) 53 | end as 'DB State', 54 | database_transaction_log_record_count as [Log Records], 55 | database_transaction_log_bytes_used / 1024 as [Log KB Used], 56 | database_transaction_log_bytes_reserved / 1024 as [Log KB Reserved], 57 | database_transaction_log_bytes_used_system / 1024 as [Log KB Used (System)], 58 | database_transaction_log_bytes_reserved_system / 1024 as [Log KB Reserved (System)], 59 | database_transaction_replicate_record_count as [Replication Records], 60 | command as [Command Type], 61 | total_elapsed_time as [Elapsed Time], 62 | cpu_time as [CPU Time], 63 | wait_type as [Wait Type], 64 | wait_time as [Wait Time], 65 | wait_resource as [Wait Resource], 66 | reads as [Reads], 67 | logical_reads as [Logical Reads], 68 | writes as [Writes], 69 | --open_transaction_count as [Open Transactions], 70 | open_resultset_count as [Open Result Sets], 71 | row_count as [Rows Returned], 72 | nest_level as [Nest Level], 73 | granted_query_memory as [Query Memory], 74 | SUBSTRING(SQLText.text,ExecReqs.statement_start_offset/2,(CASE WHEN ExecReqs.statement_end_offset = -1 then LEN(CONVERT(nvarchar(max), SQLText.text)) * 2 ELSE ExecReqs.statement_end_offset end - ExecReqs.statement_start_offset)/2) AS query_text 75 | from 76 | sys.dm_tran_active_transactions ActiveTrans (nolock) 77 | inner join sys.dm_tran_database_transactions DBTrans (nolock) 78 | on DBTrans.transaction_id = ActiveTrans.transaction_id 79 | inner join sys.databases DB (nolock) 80 | on DB.database_id = DBTrans.database_id 81 | left join sys.dm_tran_session_transactions SessionTrans (nolock) 82 | on SessionTrans.transaction_id = ActiveTrans.transaction_id 83 | left join sys.dm_exec_requests ExecReqs (nolock) 84 | on ExecReqs.session_id = SessionTrans.session_id 85 | and ExecReqs.transaction_id = SessionTrans.transaction_id 86 | outer apply sys.dm_exec_sql_text(ExecReqs.sql_handle) AS SQLText 87 | --where SessionTrans.session_id is not null -- comment this out to see SQL Server internal processes -------------------------------------------------------------------------------- /SQL Server/generators/deadlock generator.sql: -------------------------------------------------------------------------------- 1 | set nocount on 2 | 3 | if object_id('DeadlockTest') is not null 4 | drop table DeadlockTest 5 | 6 | create table DeadlockTest 7 | ( 8 | Deadlock_Key int primary key clustered, 9 | Deadlock_Count int 10 | ) 11 | go 12 | 13 | if exists (select * from sysobjects where id = object_id(N'sp_simulatedeadlock') 14 | AND objectproperty(id, N'IsProcedure') = 1) 15 | drop procedure sp_simulatedeadlock 16 | GO 17 | 18 | create procedure sp_simulatedeadlock 19 | ( 20 | @MaxDeadlocks int = -1 -- specify the number of deadlocks you want; -1 = constant deadlocking 21 | ) 22 | as begin 23 | 24 | set nocount on 25 | 26 | if object_id('DeadlockTest') is null 27 | return 28 | 29 | -- Volunteer to be a deadlock victim. 30 | set deadlock_priority low 31 | 32 | declare @DeadlockCount int 33 | 34 | select @DeadlockCount = Deadlock_Count -- this starts at 0 35 | from DeadlockTest 36 | where Deadlock_Key = 2 37 | 38 | -- Trace the start of each deadlock event. 39 | -- To listen to the trace event, setup a SQL Server Profiler trace with event class "UserConfigurable:0". 40 | -- Note that the user running this proc must have ALTER TRACE permission. 41 | -- Also note that there are only 128 characters allowed in the trace text. 42 | declare @trace nvarchar(128) 43 | 44 | if @MaxDeadlocks > 0 AND @DeadlockCount > @MaxDeadlocks 45 | begin 46 | 47 | set @trace = N'Deadlock Test @MaxDeadlocks: ' + cast(@MaxDeadlocks as nvarchar) + N' @DeadlockCount: ' + cast(@DeadlockCount as nvarchar) + N' Resetting deadlock count. Will not cause deadlock.' 48 | exec sp_trace_generateevent 49 | @eventid = 82, -- 82 = UserConfigurable:0 through 91 = UserConfigurable:9 50 | @userinfo = @trace 51 | 52 | -- Reset the number of deadlocks. 53 | -- Hopefully if there is an outer transaction, it will complete and persist this change. 54 | update DeadlockTest 55 | set Deadlock_Count = 0 56 | where Deadlock_Key = 2 57 | return 58 | end 59 | 60 | set @trace = N'Deadlock Test @MaxDeadlocks: ' + cast(@MaxDeadlocks as nvarchar) + N' @DeadlockCount: ' + cast(@DeadlockCount as nvarchar) + N' Simulating deadlock.' 61 | exec sp_trace_generateevent 62 | @eventid = 82, -- 82 = UserConfigurable:0 through 91 = UserConfigurable:9 63 | @userinfo = @trace 64 | 65 | declare @StartedTransaction bit 66 | set @StartedTransaction = 0 67 | if @@trancount = 0 68 | begin 69 | set @StartedTransaction = 1 70 | begin transaction 71 | end 72 | 73 | -- lock 2nd record 74 | update DeadlockTest 75 | set Deadlock_Count = Deadlock_Count 76 | from DeadlockTest 77 | where Deadlock_Key = 2 78 | 79 | -- lock 1st record to cause deadlock 80 | update DeadlockTest 81 | set Deadlock_Count = Deadlock_Count 82 | from DeadlockTest 83 | where Deadlock_Key = 1 84 | 85 | if @StartedTransaction = 1 86 | rollback 87 | end 88 | go 89 | 90 | insert into DeadlockTest(Deadlock_Key, Deadlock_Count) 91 | select 1, 0 92 | union select 2, 0 93 | 94 | -- Force other processes to be the deadlock victim. 95 | set deadlock_priority high 96 | 97 | begin transaction 98 | 99 | while 1 = 1 100 | begin 101 | 102 | begin try 103 | 104 | begin transaction 105 | 106 | -- lock 1st record 107 | update DeadlockTest 108 | set Deadlock_Count = Deadlock_Count 109 | from DeadlockTest 110 | where Deadlock_Key = 1 111 | 112 | waitfor delay '00:00:10' 113 | 114 | -- lock 2nd record (which will be locked when the target proc calls sp_simulatedeadlock) 115 | update DeadlockTest 116 | set Deadlock_Count = Deadlock_Count 117 | from DeadlockTest 118 | where Deadlock_Key = 2 119 | 120 | rollback 121 | 122 | end try 123 | begin catch 124 | print 'Error ' + convert(varchar(20), ERROR_NUMBER()) + ': ' + ERROR_MESSAGE() 125 | goto cleanup 126 | end catch 127 | 128 | end 129 | 130 | cleanup: 131 | 132 | if @@trancount > 0 133 | rollback 134 | 135 | drop procedure sp_simulatedeadlock 136 | drop table DeadlockTest -------------------------------------------------------------------------------- /SQL Server/maintenance/service script.sql: -------------------------------------------------------------------------------- 1 | select * from dbatools.v_show_free_spacedata_all 2 | --alter database ut1gl set recovery simple 3 | dbcc shrinkfile(2,15000) 4 | go 5 | -- »ндексы 6 | select * from dbatools.fn_cluster_index_for_smart_rebuild(8,1000000000,10.00) i 7 | go 8 | select * from dbatools.fn_index_for_smart_rebuild(8,1000000000,10.00) i 9 | go 10 | 11 | exec dbatools.sp_clear_expired_smart_reindex 12 | go 13 | 14 | exec dbatools.sp_smart_cluster_reindex @min_page_count = 8, 15 | @max_page_count=9223372036854775807, 16 | @avg_per = 10.00, 17 | @debug_info = 1 18 | go 19 | 20 | exec dbatools.sp_smart_reindex @min_page_count = 8, 21 | @max_page_count=9223372036854775807, 22 | @avg_per = 10.00, 23 | @debug_info = 1, 24 | @is_online=1 25 | go 26 | 27 | exec sp_updatestats 28 | go 29 | 30 | select * from dbatools.rep_service_index 31 | order by start_time desc 32 | go 33 | 34 | select * from dbatools.v_date_diff_last_smart_reindex 35 | go 36 | 37 | delete from dbatools.rep_service_index 38 | go 39 | 40 | select * from dbatools.v_indexes i 41 | where 42 | schema_name not in ('sys','dbatools') 43 | and data_space = 'PRIMARY' 44 | and index_id > 1 45 | 46 | -- список индексов, по которым нет статистики 47 | select 48 | quotename(i.schema_name)+'.'+quotename(i.object_name) as [object], 49 | i.index_id, quotename(i.index_name) as index_name, 50 | i.type_desc, i.data_space, i.part_count,si.rowcnt,'DROP INDEX '+QUOTENAME(i.index_name)+' ON '+QUOTENAME(i.object_name) 51 | FROM dbatools.v_indexes i 52 | inner join sys.sysindexes si on si.id = i.object_id and si.indid = i.index_id 53 | where schema_name not in ('sys','dbatools') 54 | and not exists(select * from dbatools.v_indexes_usage_stats 55 | where object_id = i.object_id and index_id = i.index_id) 56 | and i.is_primary_key = 0 and is_unique = 0 and index_id > 0 57 | order by object_name,index_id 58 | go 59 | 60 | -- список неиспользуемых индексов 61 | select 62 | quotename(i.schema_name)+'.'+quotename(i.object_name) as [object], 63 | i.index_id, quotename(i.index_name) as index_name, 64 | i.type_desc, i.data_space, i.part_count,si.rowcnt, i.user_lookups,i.is_disabled, 65 | 'DROP INDEX '+QUOTENAME(i.index_name)+' ON '+QUOTENAME(i.object_name) 66 | from dbatools.v_indexes_usage_stats i 67 | inner join sys.sysindexes si on si.id = i.object_id and si.indid = i.index_id 68 | where schema_name not in ('sys','dbatools') 69 | and i.is_primary_key = 0 and is_unique = 0 70 | and user_seeks = 0 and user_scans = 0 and index_id > 0 71 | order by object_name,index_id 72 | go 73 | 74 | -- ƒетальна¤ статистика по индексам (выбранные таблицы) 75 | select quotename(schema_name)+'.'+quotename(object_name) as [object], 76 | quotename(index_name) as index_name,type_desc,si.rowcnt, 77 | user_seeks,user_scans,user_lookups,is_unique,data_space,part_count 78 | from dbatools.v_indexes_usage_stats s 79 | inner join sys.sysindexes si on si.id = s.object_id and si.indid = s.index_id 80 | where schema_name not in ('dbatools','sys') and index_id > 0 81 | and is_disabled = 0 82 | and object_name in ('PreTransferConsumers') -- таблица 83 | order by s.object_name,s.user_seeks desc,s.user_scans desc 84 | GO 85 | 86 | -- »ндексы вызывающие издержки 87 | SELECT TOP 100 88 | [Total Cost] = ROUND(avg_total_user_cost * avg_user_impact * (user_seeks + user_scans),0), 89 | avg_user_impact, 90 | TableName = statement, 91 | [EqualityUsage] = equality_columns, 92 | [InequalityUsage] = inequality_columns, 93 | [Include Cloumns] = included_columns, 94 | s.user_seeks, 95 | s.user_scans, 96 | s.last_user_seek, 97 | s.last_user_scan 98 | FROM sys.dm_db_missing_index_groups g 99 | INNER JOIN sys.dm_db_missing_index_group_stats s ON s.group_handle = g.index_group_handle 100 | INNER JOIN sys.dm_db_missing_index_details d ON d.index_handle = g.index_handle 101 | ORDER BY s.last_user_seek DESC 102 | 103 | WHERE database_id = DB_ID() and user_seeks >5 --and last_user_seek >= '20130301' 104 | ORDER BY [statement], s.user_seeks desc 105 | 106 | SELECT r.*,p.* 107 | FROM sys.dm_exec_query_stats r 108 | CROSS APPLY sys.dm_exec_query_plan(r.plan_handle) p 109 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Instance/Between Instance.ssmssqlproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2015-08-15T16:59:49.8474297+03:00 8 | SQL 9 | 192.168.56.11 10 | sa 11 | SQL 12 | 13 | 15 14 | 0 15 | NotSpecified 16 | 17 | 18 | 19 | 2015-08-15T17:00:02.9060409+03:00 20 | SQL 21 | 192.168.56.12 22 | sa 23 | SQL 24 | 25 | 15 26 | 0 27 | NotSpecified 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.12:False:sa 36 | 192.168.56.12 37 | sa 38 | 00 introduce.sql 39 | 40 | 41 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.12:False:sa 42 | 192.168.56.12 43 | sa 44 | 01 Create TargetInst.sql 45 | 46 | 47 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.11:False:sa 48 | 192.168.56.11 49 | sa 50 | 02 Create InitiatorInst.sql 51 | 52 | 53 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.12:False:sa 54 | 192.168.56.12 55 | sa 56 | 03 Continue TargetInst.sql 57 | 58 | 59 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.11:False:sa 60 | 192.168.56.11 61 | sa 62 | 04 Start Dialog and Send Message.sql 63 | 64 | 65 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.12:False:sa 66 | 192.168.56.12 67 | sa 68 | 05 Receive request and send responce.sql 69 | 70 | 71 | 8c91a03d-f9b4-46c0-a305-b5dcc79ff907:192.168.56.11:False:sa 72 | 192.168.56.11 73 | sa 74 | 06 Receive responce and close dialog.sql 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Database/04 Begin dialog and Send message.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Переключение в базу данных InitiatorDB 3 | 4 | Чтобы переключить контекст в базу данных InitiatorDB, в которой инициируется диалог. 5 | */ 6 | USE InitiatorDB; 7 | GO 8 | 9 | /* 10 | Начало диалога и отправка сообщения-запроса 11 | 12 | Начать диалог и отправить сообщение-запрос к службе //TgtDB/2DBSample/TargetService в базе данных TargetDB. 13 | Этот код необходимо запускать единым блоком, поскольку для передачи дескриптора диалога из инструкции 14 | BEGIN DIALOG в инструкцию SEND используется переменная. Пакет запускает инструкцию BEGIN DIALOG, чтобы 15 | начать диалог и создать сообщение-запрос. Затем в инструкции SEND используется дескриптор диалога, чтобы 16 | отправить в этом диалоге сообщение-запрос. Последняя инструкция SELECT выводит текст отправленного сообщения. 17 | */ 18 | DECLARE @InitDlgHandle UNIQUEIDENTIFIER; 19 | DECLARE @RequestMsg NVARCHAR(100); 20 | 21 | BEGIN TRANSACTION; 22 | 23 | BEGIN DIALOG @InitDlgHandle 24 | FROM SERVICE [//InitDB/2DBSample/InitiatorService] 25 | TO SERVICE N'//TgtDB/2DBSample/TargetService' 26 | ON CONTRACT [//BothDB/2DBSample/SimpleContract] 27 | WITH 28 | ENCRYPTION = OFF; 29 | 30 | SELECT @RequestMsg = 31 | N'Message for Target service.'; 32 | 33 | SEND ON CONVERSATION @InitDlgHandle 34 | MESSAGE TYPE [//BothDB/2DBSample/RequestMessage] 35 | (@RequestMsg); 36 | 37 | SELECT @RequestMsg AS SentRequestMsg; 38 | 39 | COMMIT TRANSACTION; 40 | GO 41 | /* 42 | Переключение в базу данных TargetDB 43 | 44 | Переключить контекст в базу данных TargetDB, в которой будет получено сообщение-запрос 45 | и отправлено ответное сообщение в базу данных InitiatorDB. 46 | */ 47 | USE TargetDB; 48 | GO 49 | 50 | /* 51 | Получение запроса и отправка ответа 52 | 53 | Получить ответное сообщение из базы данных TargetQueue2DB и отправить ответное сообщение 54 | вызывающей стороне. Инструкция RECEIVE получает сообщение-запрос. Затем следующая инструкция 55 | SELECT выводит текст, позволяющий убедиться, что получено то же сообщение, что было отправлено 56 | на предыдущем шаге. Инструкция IF проверяет, имеет ли полученное сообщение тип запроса и 57 | используется ли инструкция SEND для отправки ответного сообщения инициатору. Она также проверяет, 58 | используется ли инструкция END CONVERSATION для завершения диалога на стороне цели. 59 | Последняя инструкция SELECT выводит текст ответного сообщения. 60 | */ 61 | DECLARE @RecvReqDlgHandle UNIQUEIDENTIFIER; 62 | DECLARE @RecvReqMsg NVARCHAR(100); 63 | DECLARE @RecvReqMsgName sysname; 64 | 65 | BEGIN TRANSACTION; 66 | 67 | WAITFOR 68 | ( RECEIVE TOP(1) 69 | @RecvReqDlgHandle = conversation_handle, 70 | @RecvReqMsg = message_body, 71 | @RecvReqMsgName = message_type_name 72 | FROM TargetQueue2DB 73 | ), TIMEOUT 1000; 74 | 75 | SELECT @RecvReqMsg AS ReceivedRequestMsg; 76 | 77 | IF @RecvReqMsgName = 78 | N'//BothDB/2DBSample/RequestMessage' 79 | BEGIN 80 | DECLARE @ReplyMsg NVARCHAR(100); 81 | SELECT @ReplyMsg = 82 | N'Message for Initiator service.'; 83 | 84 | SEND ON CONVERSATION @RecvReqDlgHandle 85 | MESSAGE TYPE 86 | [//BothDB/2DBSample/ReplyMessage] (@ReplyMsg); 87 | 88 | END CONVERSATION @RecvReqDlgHandle; 89 | END 90 | 91 | SELECT @ReplyMsg AS SentReplyMsg; 92 | 93 | COMMIT TRANSACTION; 94 | GO 95 | 96 | /* 97 | Переключение в базу данных InitiatorDB 98 | 99 | Переключить контекст обратно в базу данных InitiatorDB, в которой будет получено ответное сообщение и завершится диалог. 100 | */ 101 | USE InitiatorDB; 102 | GO 103 | 104 | /* 105 | Получение ответа и завершение диалога 106 | 107 | Получить ответное сообщение и завершить диалог. Инструкция RECEIVE получает сообщение ответа из базы данных 108 | InitiatorQueue2DB. Инструкция END CONVERSATION завершает работу инициирующей стороны диалога. Последняя 109 | инструкция SELECT выводит текст ответного сообщения, что позволяет убедиться в том, что оно совпадает с 110 | сообщением, отправленным на предыдущем шаге. 111 | */ 112 | DECLARE @RecvReplyMsg NVARCHAR(100); 113 | DECLARE @RecvReplyDlgHandle UNIQUEIDENTIFIER; 114 | 115 | BEGIN TRANSACTION; 116 | 117 | WAITFOR 118 | ( RECEIVE TOP(1) 119 | @RecvReplyDlgHandle = conversation_handle, 120 | @RecvReplyMsg = message_body 121 | FROM InitiatorQueue2DB 122 | ), TIMEOUT 1000; 123 | 124 | END CONVERSATION @RecvReplyDlgHandle; 125 | 126 | -- Display recieved request. 127 | SELECT @RecvReplyMsg AS ReceivedReplyMsg; 128 | 129 | COMMIT TRANSACTION; 130 | GO 131 | 132 | -------------------------------------------------------------------------------- /SQL Server/user grant script.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Скриптование прав пользователя. 3 | Он больше не генерирует скрипт для базы на которых нет прав. Для баз на которых есть права сделана проверка на наличие самого пользователя. 4 | */ 5 | declare @DatabaseName varchar(255) 6 | declare @UserName varchar(255) 7 | set @UserName = 'ContentDeliveryManager' 8 | declare @SQL varchar(8000) 9 | DECLARE @SqlCommand TABLE (Id int Identity (1,1), SqlText varchar(8000)) 10 | DECLARE @SqlCommandResult TABLE (Id int Identity (1,1), SqlText varchar(8000)) 11 | declare @CommandExists bit 12 | declare curDB cursor for 13 | select name 14 | from sys.sysdatabases 15 | where name in ('avant2', 'Clubs2', 'Content', 'horoscope', 'monitoring', 'Report', 'send', 'subscribe') 16 | and status&512 = 0 17 | order by name 18 | open curDB 19 | fetch next from curDB 20 | into @DatabaseName 21 | while @@fetch_status=0 22 | begin 23 | set @CommandExists = 0 24 | delete from @SqlCommand 25 | 26 | insert into @SqlCommand (SqlText) 27 | select 'use '+@DatabaseName 28 | --заводим пользователя в БД 29 | insert into @SqlCommand (SqlText) 30 | select 'if not exists(select name from sys.database_principals where type in (''S'',''U'') and name = '''+@UserName+''') 31 | CREATE USER ['+@UserName+'] FOR LOGIN ['+@UserName+']' 32 | 33 | --включение в роли 34 | insert into @SqlCommand (SqlText) 35 | select '-- включение в роли' 36 | set @SQL = 'use '+@DatabaseName+' 37 | declare @UserName varchar(255) 38 | set @UserName = '''+@UserName+''' 39 | SELECT 40 | ''EXEC sp_addrolemember N''''''+b.name+'''''', N''''''+bm.name+'''''''' 41 | FROM sys.database_role_members AS a 42 | INNER JOIN sys.database_principals AS b ON a.role_principal_id = b.principal_id 43 | INNER JOIN sys.database_principals AS bm ON a.member_principal_id = bm.principal_id 44 | where bm.name = @UserName' 45 | insert into @SqlCommand (SqlText) 46 | execute (@SQL) 47 | if @@rowcount>0 set @CommandExists = 1 48 | 49 | --права БД 50 | insert into @SqlCommand (SqlText) 51 | select '-- права БД' 52 | set @SQL = 53 | 'use '+@DatabaseName+' 54 | declare @UserName varchar(255) 55 | set @UserName = '''+@UserName+''' 56 | select 57 | p.State_Desc+ '' '' 58 | +Permission_Name COLLATE Cyrillic_General_CI_AS + '' TO [''+@UserName+'']'' as Sqltext 59 | from sys.database_permissions p 60 | inner join sys.sysusers u on u.uid=p.grantee_principal_id 61 | where class = 0 62 | and u.name = @UserName 63 | ' 64 | insert into @SqlCommand (SqlText) 65 | execute (@SQL) 66 | if @@rowcount>0 set @CommandExists = 1 67 | 68 | --права на схемы 69 | insert into @SqlCommand (SqlText) 70 | select '-- права схемы' 71 | set @SQL = 72 | 'use '+@DatabaseName+' 73 | declare @UserName varchar(255) 74 | set @UserName = '''+@UserName+''' 75 | select 76 | p.State_Desc+ '' '' 77 | +Permission_Name COLLATE Cyrillic_General_CI_AS + '' ON SCHEMA::['' 78 | +s.name+''] TO [''+@UserName+'']'' as Sqltext--, 79 | --o.type_desc, s.name, o.name, u.name as grantee,ug.name as grantor, * 80 | from sys.database_permissions p 81 | inner join sys.schemas s on p.major_id=s.schema_id 82 | inner join sys.sysusers u on u.uid=p.grantee_principal_id 83 | inner join sys.sysusers ug on ug.uid=p.grantor_principal_id 84 | where class = 3 85 | and u.name = @UserName 86 | order by s.name 87 | ' 88 | insert into @SqlCommand (SqlText) 89 | execute (@SQL) 90 | if @@rowcount>0 set @CommandExists = 1 91 | 92 | --права на объекты БД 93 | insert into @SqlCommand (SqlText) 94 | select '-- права на объекты БД' 95 | set @SQL = 96 | 'use '+@DatabaseName+' 97 | declare @UserName varchar(255) 98 | set @UserName = '''+@UserName+''' 99 | select 100 | p.State_Desc+ '' '' 101 | +Permission_Name COLLATE Cyrillic_General_CI_AS + '' ON OBJECT::['' 102 | +s.name+''].['' 103 | +o.name 104 | +''] TO [''+@UserName+'']'' as Sqltext--, 105 | --o.type_desc, s.name, o.name, u.name as grantee,ug.name as grantor, * 106 | from sys.database_permissions p 107 | inner join sys.objects o on p.major_id=o.object_id 108 | inner join sys.schemas s on o.schema_id=s.schema_id 109 | inner join sys.sysusers u on u.uid=p.grantee_principal_id 110 | left join sys.sysusers ug on ug.uid=p.grantor_principal_id 111 | where class = 1 112 | and u.name = @UserName 113 | order by s.name, o.name 114 | ' 115 | insert into @SqlCommand (SqlText) 116 | execute (@SQL) 117 | if @@rowcount>0 set @CommandExists = 1 118 | 119 | --Если были значимые команды то переносим в результирующую таблицу 120 | if @CommandExists = 1 121 | begin 122 | insert into @SqlCommandResult (SqlText) 123 | select SqlText from @SqlCommand order by Id 124 | end 125 | 126 | fetch next from curDB 127 | into @DatabaseName 128 | end 129 | close curDB 130 | deallocate curDB 131 | select * from @SqlCommandResult 132 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Instance/01 Create TargetInst.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Создание конечной точки компонента Service Broker 3 | 4 | Cоздать конечную точку компонента Service Broker для данного экземпляра компонента Database Engine. 5 | Конечная точка компонента Service Broker определяет сетевой адрес, на который отправляются сообщения 6 | компонента Service Broker. Эта конечная точка по умолчанию компонента Service Broker использует 7 | TCP-порт 4022 и определяет, что удаленные экземпляры компонента Database Engine будут использовать 8 | для отправки сообщений соединения с проверкой подлинности Windows. 9 | 10 | Проверка подлинности Windows работает, если оба компьютера находятся в одном домене или в доверенных доменах. 11 | Если компьютеры не расположены в доверенных доменах, используйте для защиты конечных точек сертификаты безопасности. 12 | Дополнительные сведения см. в разделе Как создать сертификаты для безопасности транспорта компонента Service Broker (Transact-SQL). 13 | */ 14 | USE master; 15 | GO 16 | IF EXISTS (SELECT * FROM master.sys.endpoints 17 | WHERE name = N'InstTargetEndpoint') 18 | DROP ENDPOINT InstTargetEndpoint; 19 | GO 20 | CREATE ENDPOINT InstTargetEndpoint 21 | STATE = STARTED 22 | AS TCP ( LISTENER_PORT = 4022 ) 23 | FOR SERVICE_BROKER (AUTHENTICATION = WINDOWS ); 24 | GO 25 | 26 | /* 27 | Создание целевой базы данных, главного ключа и пользователя 28 | 29 | Измените пароль в инструкции CREATE MASTER KEY. Затем выполните код, чтобы создать целевую базу данных, 30 | которая будет использоваться для этого учебника. По умолчанию в новых базах данных включен параметр 31 | ENABLE_BROKER. Этот код также создает главный ключ и имя пользователя, которое будет применяться для 32 | поддержки шифрования и удаленных соединений. 33 | */ 34 | USE master; 35 | GO 36 | IF EXISTS (SELECT * FROM sys.databases 37 | WHERE name = N'InstTargetDB') 38 | DROP DATABASE InstTargetDB; 39 | GO 40 | CREATE DATABASE InstTargetDB; 41 | GO 42 | 43 | ALTER DATABASE InstTargetDB SET ENABLE_BROKER; 44 | GO 45 | 46 | USE InstTargetDB; 47 | GO 48 | 49 | 50 | CREATE MASTER KEY 51 | ENCRYPTION BY PASSWORD = N'q1w2e3R$T%Y^'; 52 | GO 53 | 54 | CREATE USER TargetUser WITHOUT LOGIN; 55 | GO 56 | /* 57 | Создание целевого сертификата 58 | 59 | Измените имя файла, указанное в инструкции BACKUP CERTIFICATE, чтобы оно указывало 60 | на папку, расположенную на текущем компьютере. Затем выполните код, чтобы создать 61 | целевой сертификат, который будет использоваться для шифрования сообщений. В указанной 62 | папке должны быть заданы разрешения, предотвращающие доступ любых учетных записей, 63 | кроме учетной записи Windows текущего пользователя и учетной записи Windows, с которой 64 | работает экземпляр компонента Database Engine. Для занятия 2 необходимо вручную скопировать 65 | файл InstTargetCertificate.cer в папку, доступ к которой будет осуществляться из 66 | инициирующего экземпляра. 67 | */ 68 | CREATE CERTIFICATE InstTargetCertificate 69 | AUTHORIZATION TargetUser 70 | WITH SUBJECT = 'Target Certificate', 71 | EXPIRY_DATE = N'20161231'; 72 | 73 | BACKUP CERTIFICATE InstTargetCertificate 74 | TO FILE = 75 | N'C:\SQL\InstTargetCertificate.cer'; 76 | GO 77 | 78 | /* 79 | Создание типов сообщений 80 | 81 | Выполните его, чтобы создать типы сообщений для диалога. Заданные здесь имена и 82 | свойства типов сообщений должны быть идентичны тем, которые будут созданы в базе 83 | данных InstInitiatorDB на следующем занятии. 84 | */ 85 | CREATE MESSAGE TYPE [//BothDB/2InstSample/RequestMessage] 86 | VALIDATION = WELL_FORMED_XML; 87 | CREATE MESSAGE TYPE [//BothDB/2InstSample/ReplyMessage] 88 | VALIDATION = WELL_FORMED_XML; 89 | GO 90 | 91 | /* 92 | Создание контракта 93 | 94 | Чтобы создать контракт для диалога. Заданное здесь имя и свойства контракта 95 | должны быть такими же, как в контракте, который будет создан в базе данных 96 | InstInitiatorDB на следующем занятии. 97 | */ 98 | CREATE CONTRACT [//BothDB/2InstSample/SimpleContract] 99 | ([//BothDB/2InstSample/RequestMessage] 100 | SENT BY INITIATOR, 101 | [//BothDB/2InstSample/ReplyMessage] 102 | SENT BY TARGET 103 | ); 104 | GO 105 | /* 106 | Создание очереди и службы целевой стороны 107 | 108 | Чтобы создать очередь и службу, которые будут использоваться для целевой стороны. 109 | Инструкция CREATE SERVICE связывает службу с очередью InstTargetQueue, чтобы все 110 | сообщения, отправленные службе, были получены очередью InstTargetQueue. Инструкция 111 | CREATE SERVICE также указывает, что использовать службу в качестве целевой могут 112 | только диалоги, использующие ранее созданный контракт //BothDB/2InstSample/SimpleContract. 113 | */ 114 | CREATE QUEUE InstTargetQueue; 115 | 116 | CREATE SERVICE [//TgtDB/2InstSample/TargetService] 117 | AUTHORIZATION TargetUser 118 | ON QUEUE InstTargetQueue 119 | ([//BothDB/2InstSample/SimpleContract]); 120 | GO 121 | 122 | -------------------------------------------------------------------------------- /SQL Server/indexes/index detail show.sql: -------------------------------------------------------------------------------- 1 | BEGIN -- подготовка 2 | IF OBJECT_ID('tempdb..#v_indexes') IS NOT NULL 3 | DROP TABLE #v_indexes; 4 | IF OBJECT_ID('tempdb..#v_indexes_usage_stats') IS NOT NULL 5 | DROP TABLE #v_indexes_usage_stats; 6 | ;WITH v_indexes AS ( 7 | select 8 | SCHEMA_ID(OBJECT_SCHEMA_NAME(ix.object_id,DB_ID())) as [schema_id], 9 | OBJECT_SCHEMA_NAME(ix.object_id,DB_ID()) as [schema_name], 10 | ix.object_id as [object_id], 11 | OBJECT_NAME(ix.object_id) as [object_name], 12 | ix.index_id as [index_id], 13 | ix.Name as [index_name], 14 | ix.type, 15 | ix.type_desc, 16 | ix.is_unique, 17 | ix.data_space_id, 18 | case ds.type 19 | when 'FG' then ds.name 20 | when 'PS' then (select distinct name from sys.partition_schemes where data_space_id = ix.data_space_id) 21 | end as data_space, 22 | isnull((select fanout from sys.partition_functions prtfn 23 | join sys.partition_schemes as prtsch on prtfn.function_id = prtsch.function_id 24 | where prtsch.data_space_id = ix.data_space_id),0) as part_count, 25 | ix.ignore_dup_key, 26 | ix.is_primary_key, 27 | ix.is_unique_constraint, 28 | ix.fill_factor, 29 | ix.is_padded, 30 | ix.is_disabled, 31 | ix.is_hypothetical, 32 | ix.allow_row_locks, 33 | ix.allow_page_locks, 34 | ix.filter_definition 35 | from sys.indexes as ix 36 | join sys.data_spaces as ds on ds.data_space_id = ix.data_space_id 37 | ) 38 | SELECT * 39 | INTO #v_indexes 40 | FROM v_indexes; 41 | 42 | WITH v_indexes_usage_stats AS 43 | (select 44 | ix.schema_id, 45 | ix.schema_name, 46 | ix.object_id, 47 | ix.object_name, 48 | ix.index_id, 49 | ix.index_name, 50 | ix.type, 51 | ix.type_desc, 52 | ix.is_unique, 53 | ix.data_space_id, 54 | ix.data_space, 55 | ix.part_count, 56 | ix.ignore_dup_key, 57 | ix.is_primary_key, 58 | ix.is_unique_constraint, 59 | ix.fill_factor, 60 | ix.is_padded, 61 | ix.is_disabled, 62 | ix.is_hypothetical, 63 | ix.allow_row_locks, 64 | ix.allow_page_locks, 65 | ix.filter_definition, 66 | iu.user_seeks, 67 | iu.user_scans, 68 | iu.user_lookups, 69 | iu.system_seeks, 70 | iu.system_scans, 71 | iu.system_lookups 72 | from #v_indexes as ix 73 | join sys.dm_db_index_usage_stats as iu on iu.index_id = ix.index_id and iu.object_id = ix.object_id and iu.database_id = DB_ID() 74 | ) 75 | SELECT * 76 | INTO #v_indexes_usage_stats 77 | FROM v_indexes_usage_stats 78 | END 79 | GO 80 | -- список индексов, по которым нет статистики 81 | SELECT 'Нет статистики' AS [Tables], 82 | quotename(i.schema_name)+'.'+quotename(i.object_name) as [object], 83 | i.index_id, quotename(i.index_name) as index_name, 84 | i.type_desc, i.data_space, i.part_count,si.rowcnt,'DROP INDEX '+QUOTENAME(i.index_name)+' ON '+QUOTENAME(i.schema_name)+'.'+QUOTENAME(i.object_name) 85 | FROM #v_indexes i 86 | inner join sys.sysindexes si on si.id = i.object_id and si.indid = i.index_id 87 | where schema_name not in ('sys','dbatools') 88 | and not exists(select * from #v_indexes_usage_stats 89 | where object_id = i.object_id and index_id = i.index_id) 90 | and i.is_primary_key = 0 and is_unique = 0 and index_id > 0 91 | order by object_name,index_id 92 | go 93 | 94 | -- список неиспользуемых индексов 95 | select 'Не использованные индексы' AS [Tables], 96 | quotename(i.schema_name)+'.'+quotename(i.object_name) as [object], 97 | i.index_id, quotename(i.index_name) as index_name, 98 | i.type_desc, i.data_space, i.part_count,si.rowcnt, i.user_lookups,i.is_disabled, 99 | 'DROP INDEX '+QUOTENAME(i.index_name)+' ON '+QUOTENAME(i.schema_name)+'.'+QUOTENAME(i.object_name) 100 | from #v_indexes_usage_stats i 101 | inner join sys.sysindexes si on si.id = i.object_id and si.indid = i.index_id 102 | where schema_name not in ('sys','dbatools') 103 | and i.is_primary_key = 0 and is_unique = 0 104 | and user_seeks = 0 and user_scans = 0 and index_id > 0 105 | order by object_name,index_id 106 | go 107 | 108 | -- Детальная статистика по индексам (выбранные таблицы) 109 | select 'Детальная статистика по индексам' AS [Tables], quotename(schema_name)+'.'+quotename(object_name) as [object], 110 | quotename(index_name) as index_name,type_desc,si.rowcnt, 111 | user_seeks,user_scans,user_lookups,is_unique,data_space,part_count 112 | from #v_indexes_usage_stats s 113 | inner join sys.sysindexes si on si.id = s.object_id and si.indid = s.index_id 114 | where schema_name not in ('dbatools','sys') and index_id > 0 115 | and is_disabled = 0 116 | and object_name in ('FinInstruments') -- таблица 117 | order by s.object_name,s.user_seeks desc,s.user_scans desc 118 | GO 119 | 120 | -- Индексы вызывающие издержки 121 | SELECT TOP 100 'Индексы вызывающие издержки' AS [Tables], 122 | [Total Cost] = ROUND(avg_total_user_cost * avg_user_impact * (user_seeks + user_scans),0), 123 | avg_user_impact, 124 | TableName = statement, 125 | [EqualityUsage] = equality_columns, 126 | [InequalityUsage] = inequality_columns, 127 | [Include Cloumns] = included_columns, 128 | s.user_seeks, 129 | s.user_scans, 130 | s.last_user_seek, 131 | s.last_user_scan 132 | FROM sys.dm_db_missing_index_groups g 133 | INNER JOIN sys.dm_db_missing_index_group_stats s ON s.group_handle = g.index_group_handle 134 | INNER JOIN sys.dm_db_missing_index_details d ON d.index_handle = g.index_handle 135 | WHERE database_id = DB_ID() and user_seeks >5 --and last_user_seek >= '20130301' 136 | ORDER BY [statement], s.user_seeks desc 137 | 138 | 139 | -------------------------------------------------------------------------------- /PostgreSQL/account/check_account.sql: -------------------------------------------------------------------------------- 1 | -- Функция для проверки BIC (аналог IsBic) 2 | CREATE OR REPLACE FUNCTION is_bic_valid(bic TEXT) 3 | RETURNS BOOLEAN AS $$ 4 | BEGIN 5 | IF bic IS NULL OR LENGTH(TRIM(bic)) <> 9 OR bic !~ '^[0-9]+$' THEN 6 | RETURN FALSE; 7 | END IF; 8 | RETURN TRUE; 9 | END; 10 | $$ LANGUAGE plpgsql IMMUTABLE; 11 | 12 | -- Функция для цифровизации номера счета (аналог digitizeAccountNumber) 13 | CREATE OR REPLACE FUNCTION digitize_account_number(account_number TEXT) 14 | RETURNS TEXT AS $$ 15 | DECLARE 16 | result TEXT := ''; 17 | char_val TEXT; 18 | digit_map CONSTANT TEXT[] := ARRAY['0','1','2','3','4','5','6','7','8','9']; -- A=0, B=1, ..., X=9 19 | idx INT; 20 | BEGIN 21 | IF LENGTH(account_number) <> 20 THEN 22 | RAISE EXCEPTION 'Account number must be 20 characters'; 23 | END IF; 24 | FOR i IN 1..20 LOOP 25 | char_val := SUBSTRING(account_number, i, 1); 26 | IF i = 6 THEN 27 | -- Замена буквы на цифру 28 | idx := POSITION(UPPER(char_val) IN 'ABCEHKMPTX'); 29 | IF idx > 0 THEN 30 | result := result || digit_map[idx]; 31 | ELSIF char_val ~ '^[0-9]$' THEN 32 | result := result || char_val; 33 | ELSE 34 | RAISE EXCEPTION 'Invalid character at position 6'; 35 | END IF; 36 | ELSE 37 | IF char_val ~ '^[0-9]$' THEN 38 | result := result || char_val; 39 | ELSE 40 | RAISE EXCEPTION 'Account number must contain only digits except position 6'; 41 | END IF; 42 | END IF; 43 | END LOOP; 44 | RETURN result; 45 | END; 46 | $$ LANGUAGE plpgsql IMMUTABLE; 47 | 48 | -- Функция для расчета контрольной суммы (аналог CalculateAccountChecksum) 49 | CREATE OR REPLACE FUNCTION calculate_account_checksum(account_number TEXT, bic TEXT, bic_is_rkc BOOLEAN DEFAULT FALSE) 50 | RETURNS INTEGER AS $$ 51 | DECLARE 52 | digitized TEXT; 53 | weights CONSTANT INTEGER[] := ARRAY[ 54 | 7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1 55 | ]; -- 23 веса 56 | products INTEGER[] := ARRAY[]::INTEGER[]; 57 | sum_val INTEGER := 0; 58 | bic_part TEXT; 59 | i INT; 60 | BEGIN 61 | IF NOT is_bic_valid(bic) THEN 62 | RAISE EXCEPTION 'Invalid BIC'; 63 | END IF; 64 | digitized := digitize_account_number(account_number); 65 | IF bic_is_rkc THEN 66 | bic_part := SUBSTRING(bic, 5, 2); 67 | ELSE 68 | bic_part := SUBSTRING(bic, 7, 3); 69 | END IF; 70 | -- Строим массив для расчета 71 | FOR i IN 1..23 LOOP 72 | IF i <= 3 THEN 73 | products[i] := (SUBSTRING(bic_part, i, 1)::INTEGER) * weights[i]; 74 | ELSIF i >= 4 AND i <= 23 THEN 75 | products[i] := (SUBSTRING(digitized, i-3, 1)::INTEGER) * weights[i]; 76 | END IF; 77 | sum_val := sum_val + products[i]; 78 | END LOOP; 79 | RETURN ((sum_val % 10) * 3) % 10; 80 | END; 81 | $$ LANGUAGE plpgsql IMMUTABLE; 82 | 83 | -- Функция для раскрытия маски с вставкой checksum (аналог UnmaskBankAccount) 84 | CREATE OR REPLACE FUNCTION unmask_bank_account(mask TEXT, bic TEXT, num INTEGER) 85 | RETURNS TEXT AS $$ 86 | DECLARE 87 | unmasked TEXT := ''; 88 | num_str TEXT := LPAD(num::TEXT, 20, '0'); -- Форматируем num до 20 цифр 89 | checksum INTEGER; 90 | temp_account TEXT; 91 | i INT; 92 | x_count INT := 0; 93 | BEGIN 94 | IF mask IS NULL OR LENGTH(mask) <> 20 THEN 95 | RAISE EXCEPTION 'Mask must be 20 characters'; 96 | END IF; 97 | -- Считаем 'x' и заменяем с конца 98 | FOR i IN REVERSE 1..20 LOOP 99 | IF SUBSTRING(mask, i, 1) = 'x' THEN 100 | x_count := x_count + 1; 101 | unmasked := SUBSTRING(num_str, 21 - x_count, 1) || unmasked; 102 | ELSE 103 | unmasked := SUBSTRING(mask, i, 1) || unmasked; 104 | END IF; 105 | END LOOP; 106 | -- Рассчитываем checksum и вставляем в 9-ю позицию (заменяя 8-й символ, как в оригинале) 107 | checksum := calculate_account_checksum(unmasked, bic); 108 | temp_account := SUBSTRING(unmasked, 1, 7) || checksum::TEXT || SUBSTRING(unmasked, 9); 109 | RETURN temp_account; 110 | END; 111 | $$ LANGUAGE plpgsql IMMUTABLE; 112 | 113 | -- Функция для проверки валидности (аналог IsValidAccountNumber) 114 | CREATE OR REPLACE FUNCTION is_valid_account_number(account_number TEXT, bic TEXT, bic_is_rkc BOOLEAN DEFAULT FALSE) 115 | RETURNS BOOLEAN AS $$ 116 | DECLARE 117 | digitized TEXT; 118 | weights CONSTANT INTEGER[] := ARRAY[ 119 | 7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1 120 | ]; 121 | products INTEGER[] := ARRAY[]::INTEGER[]; 122 | sum_val INTEGER := 0; 123 | bic_part TEXT; 124 | i INT; 125 | BEGIN 126 | IF NOT is_bic_valid(bic) THEN 127 | RETURN FALSE; 128 | END IF; 129 | digitized := digitize_account_number(account_number); 130 | IF bic_is_rkc THEN 131 | bic_part := SUBSTRING(bic, 5, 2); 132 | ELSE 133 | bic_part := SUBSTRING(bic, 7, 3); 134 | END IF; 135 | FOR i IN 1..23 LOOP 136 | IF i <= 3 THEN 137 | products[i] := (SUBSTRING(bic_part, i, 1)::INTEGER) * weights[i]; 138 | ELSIF i >= 4 AND i <= 23 THEN 139 | products[i] := (SUBSTRING(digitized, i-3, 1)::INTEGER) * weights[i]; 140 | END IF; 141 | sum_val := sum_val + products[i]; 142 | END LOOP; 143 | RETURN (sum_val % 10) = 0; 144 | END; 145 | $$ LANGUAGE plpgsql IMMUTABLE; 146 | -------------------------------------------------------------------------------- /SQL Server/clr/account/README.md: -------------------------------------------------------------------------------- 1 | # Инструкция по использованию класса AccountChecksum 2 | 3 | ## Введение 4 | Класс `AccountChecksum` — это статический класс на C#, предназначенный для расчета и проверки контрольных сумм банковских номеров лицевых счетов в России согласно стандарту Центрального Банка РФ (ПОРЯДОК РАСЧЕТА КОНТРОЛЬНОГО КЛЮЧА В НОМЕРЕ ЛИЦЕВОГО СЧЕТА от 8 сентября 1997 г. № 515). Он включает методы для валидации BIC, преобразования масок, расчета checksum и проверки номеров счетов. Класс предназначен для использования в SQL Server как пользовательские функции (атрибуты `[Microsoft.SqlServer.Server.SqlFunction]`). 5 | 6 | **Предварительные требования:** 7 | - .NET Framework или .NET Core с поддержкой SQL Server CLR. 8 | - Знание BIC (9-значный код банка) и номеров лицевых счетов (20 символов, включая контрольную сумму). 9 | 10 | ## Шаг 1: Проверка BIC 11 | Используйте приватный метод `IsBic(string bic)` для валидации BIC: 12 | - BIC не должен быть пустым или состоять из пробелов. 13 | - Должен содержать только цифры. 14 | - Длина ровно 9 символов. 15 | 16 | Пример: 17 | ```csharp 18 | bool isValidBic = IsBic("044525225"); // true, если BIC валиден 19 | ``` 20 | 21 | ## Шаг 2: Преобразование маскированного номера счета 22 | Используйте приватный метод `Unmask(string mask, int num)` для замены плейсхолдеров 'x' в маске на цифры из числа `num`: 23 | - Маска — строка с 'x' (например, "12345x78901234567890"). 24 | - `num` форматируется до 20 цифр и заменяет 'x' с конца. 25 | - Возвращает строку или null, если маска пустая. 26 | 27 | Пример: 28 | ```csharp 29 | string unmasked = Unmask("12345x78901234567890", 123456789); // Результат: "12345678901234567890" 30 | ``` 31 | 32 | ## Шаг 3: Цифровизация номера счета 33 | Используйте приватный метод `digitizeAccountNumber(string accountNumber)` для замены 6-го символа, если он буква: 34 | - Допустимые буквы: A, B, C, E, H, K, M, P, T, X (заменяются на индекс 0-9). 35 | - Возвращает строку с цифрами. 36 | 37 | Пример: 38 | ```csharp 39 | string digitized = digitizeAccountNumber("12345A78901234567890"); // Результат: "12345078901234567890" 40 | ``` 41 | 42 | ## Шаг 4: Расчет взвешенных произведений 43 | Используйте приватный метод `calculateWeightedProducts(string accountNumber, string bic, bool bicIsRkc)`: 44 | - Вычисляет массив из 23 элементов на основе весов (`m_WeightsForAccountNumber`). 45 | - Для обычных BIC использует последние 3 цифры; для РКЦ (bicIsRkc=true) — 5-ю и 6-ю. 46 | - Номер счета должен быть 20 цифр. 47 | 48 | Пример: 49 | ```csharp 50 | int[] products = calculateWeightedProducts("12345678901234567890", "044525225", false); 51 | ``` 52 | 53 | ## Шаг 5: Расчет контрольной суммы 54 | Используйте публичный метод `CalculateAccountChecksum(string accountNumber, string bic, bool bicIsRkc = false)`: 55 | - Введите номер счета (20 символов) и BIC. 56 | - Метод проверит валидность, преобразует счет и рассчитает checksum: `((sum % 10) * 3) % 10`. 57 | - Бросает исключение при ошибках. 58 | 59 | Пример: 60 | ```csharp 61 | int checksum = CalculateAccountChecksum("12345678901234567890", "044525225"); // Возвращает int (0-9) 62 | ``` 63 | 64 | ## Шаг 6: Раскрытие маски с контрольной суммой 65 | Используйте публичный метод `UnmaskBankAccount(string mask, string bic, int num)`: 66 | - Раскрывает маску, рассчитывает checksum и вставляет его в 9-ю позицию (заменяя 8-й символ). 67 | - Возвращает полный 20-значный номер счета. 68 | 69 | Пример: 70 | ```csharp 71 | string fullAccount = UnmaskBankAccount("12345x78x01234567890", "044525225", 123456789); // Вставляет checksum 72 | ``` 73 | 74 | ## Шаг 7: Проверка валидности номера счета 75 | Используйте публичный метод `IsValidAccountNumber(string accountNumber, string bic, bool bicIsRkc = false)`: 76 | - Введите номер счета (20 символов) и BIC. 77 | - Возвращает true, если сумма взвешенных произведений % 10 == 0. 78 | 79 | Пример: 80 | ```csharp 81 | bool isValid = IsValidAccountNumber("12345678901234567890", "044525225"); // true или false 82 | ``` 83 | 84 | ## Примечания и советы 85 | - Все публичные методы бросают `ArgumentOutOfRangeException` при неверных входных данных (пустые строки, неправильная длина, нецифры). 86 | - Параметр `bicIsRkc` установите в true, если BIC принадлежит Расчетно-Кассовому Центру. 87 | - Для интеграции в SQL Server скомпилируйте класс в сборку и зарегистрируйте функции. 88 | - Тестируйте на реальных данных; код не обрабатывает все edge-cases (например, неиспользуемые поля как `m_WeightsForInn`). 89 | 90 | ## Установка в SQL Server 91 | Для использования класса в SQL Server выполните следующие шаги (предполагается, что DLL находится по пути `c:\clr\AccountChecksum_x64.dll` и сборка называется `AccountChecksum`): 92 | 93 | ```sql 94 | sp_configure 'advanced options',1; 95 | GO 96 | reconfigure with override; 97 | GO 98 | sp_configure 'clr enabled',1 99 | GO 100 | reconfigure with override; 101 | GO 102 | 103 | create assembly [AccountChecksum] 104 | from 'c:\clr\AccountChecksum_x64.dll' 105 | with permission_set = safe; 106 | GO 107 | 108 | create function dbo.UnmaskBankAccount(@mask nvarchar(20),@bic nvarchar(9),@num int) returns nvarchar(50) 109 | as external name [AccountChecksum].[AccountChecksum].UnmaskBankAccount 110 | GO 111 | 112 | create function dbo.CalculateAccountChecksum(@accountNumber nvarchar(20),@bic nvarchar(9),@bicIsRkc bit=false) returns int 113 | as external name [AccountChecksum].[AccountChecksum].CalculateAccountChecksum 114 | GO 115 | 116 | create function dbo.IsValidAccountNumber(@accountNumber nvarchar(20),@bic nvarchar(9),@bicIsRkc bit=false) returns bit 117 | as external name [AccountChecksum].[AccountChecksum].IsValidAccountNumber 118 | GO 119 | ``` 120 | 121 | Если нужны примеры кода или дополнительные детали, уточните. -------------------------------------------------------------------------------- /SQL Server/User grant script v2.sql: -------------------------------------------------------------------------------- 1 | ----------------------------------------------- Скриптование прав пользователя ----------------------------------------------------- 2 | declare @loginName sysname = '@-DIRECT\smsmail' 3 | , @UserName sysname 4 | , @DatabaseName varchar(255) 5 | , @sql nvarchar(max) 6 | , @CommandExists bit 7 | 8 | DECLARE @SqlCommand TABLE (Id int Identity (1,1), SqlText varchar(8000)) 9 | DECLARE @SqlCommandResult TABLE (Id int Identity (1,1), SqlText varchar(8000)) 10 | 11 | declare curDB cursor for 12 | /* -- для всех баз 13 | select name 14 | from sys.databases 15 | where source_database_id is null 16 | and state_desc = 'ONLINE' 17 | order by name 18 | */ 19 | -- только для БД, которые не являются вторичными репликами 20 | select db.name 21 | from sys.databases db left join sys.dm_hadr_availability_replica_states hars 22 | on db.replica_id = hars.replica_id 23 | where hars.role_desc = 'PRIMARY' 24 | or hars.role_desc is null 25 | and db.[state] = 0 26 | and db.source_database_id is null 27 | order by db.name 28 | 29 | open curDB 30 | 31 | fetch next from curDB 32 | into @DatabaseName 33 | 34 | while @@fetch_status = 0 35 | begin 36 | set @CommandExists = 0 37 | delete from @SqlCommand 38 | 39 | insert into @SqlCommand (SqlText) 40 | select 'use '+ @DatabaseName 41 | 42 | set @SQL= ( 'select @UserName = name from ' + @DatabaseName + '.' + 'sys.sysusers 43 | where [sid] = ( select [sid] from sys.syslogins where name = ' + '''' + @loginName + '''' + ')' ) 44 | -- print(@sql) 45 | 46 | exec sp_executesql @sql, N'@UserName sysname out', @UserName out 47 | 48 | --заводим пользователя в БД 49 | insert into @SqlCommand (SqlText) 50 | select 'if not exists(select name from sys.database_principals where type in (''S'',''U'') and name = '''+@UserName+''') 51 | CREATE USER ['+@UserName+'] FOR LOGIN ['+@UserName+']' 52 | 53 | --включение в роли 54 | insert into @SqlCommand (SqlText) 55 | select '-- включение в роли' 56 | set @SQL = 'use '+@DatabaseName+' 57 | declare @UserName varchar(255) 58 | set @UserName = '''+@UserName+''' 59 | SELECT 60 | ''EXEC sp_addrolemember N''''''+b.name+'''''', N''''''+bm.name+'''''''' 61 | FROM sys.database_role_members AS a 62 | INNER JOIN sys.database_principals AS b ON a.role_principal_id = b.principal_id 63 | INNER JOIN sys.database_principals AS bm ON a.member_principal_id = bm.principal_id 64 | where bm.name = @UserName' 65 | insert into @SqlCommand (SqlText) 66 | execute (@SQL) 67 | if @@rowcount>0 set @CommandExists = 1 68 | 69 | --права БД 70 | insert into @SqlCommand (SqlText) 71 | select '-- права БД' 72 | set @SQL = 73 | 'use '+@DatabaseName+' 74 | declare @UserName varchar(255) 75 | set @UserName = '''+@UserName+''' 76 | select 77 | p.State_Desc+ '' '' 78 | +Permission_Name COLLATE Cyrillic_General_CI_AS + '' TO [''+@UserName+'']'' as Sqltext 79 | from sys.database_permissions p 80 | inner join sys.sysusers u on u.uid=p.grantee_principal_id 81 | where class = 0 82 | and u.name = @UserName 83 | ' 84 | insert into @SqlCommand (SqlText) 85 | execute (@SQL) 86 | if @@rowcount>0 set @CommandExists = 1 87 | 88 | --права на схемы 89 | insert into @SqlCommand (SqlText) 90 | select '-- права схемы' 91 | set @SQL = 92 | 'use '+@DatabaseName+' 93 | declare @UserName varchar(255) 94 | set @UserName = '''+@UserName+''' 95 | select 96 | p.State_Desc+ '' '' 97 | +Permission_Name COLLATE Cyrillic_General_CI_AS + '' ON SCHEMA::['' 98 | +s.name+''] TO [''+@UserName+'']'' as Sqltext--, 99 | --o.type_desc, s.name, o.name, u.name as grantee,ug.name as grantor, * 100 | from sys.database_permissions p 101 | inner join sys.schemas s on p.major_id=s.schema_id 102 | inner join sys.sysusers u on u.uid=p.grantee_principal_id 103 | inner join sys.sysusers ug on ug.uid=p.grantor_principal_id 104 | where class = 3 105 | and u.name = @UserName 106 | order by s.name 107 | ' 108 | insert into @SqlCommand (SqlText) 109 | execute (@SQL) 110 | if @@rowcount>0 set @CommandExists = 1 111 | 112 | --права на объекты БД 113 | insert into @SqlCommand (SqlText) 114 | select '-- права на объекты БД' 115 | set @SQL = 116 | 'use '+@DatabaseName+' 117 | declare @UserName varchar(255) 118 | set @UserName = '''+@UserName+''' 119 | select 120 | p.State_Desc+ '' '' 121 | +Permission_Name COLLATE Cyrillic_General_CI_AS + '' ON OBJECT::['' 122 | +s.name+''].['' 123 | +o.name 124 | +''] TO [''+@UserName+'']'' as Sqltext--, 125 | --o.type_desc, s.name, o.name, u.name as grantee,ug.name as grantor, * 126 | from sys.database_permissions p 127 | inner join sys.objects o on p.major_id=o.object_id 128 | inner join sys.schemas s on o.schema_id=s.schema_id 129 | inner join sys.sysusers u on u.uid=p.grantee_principal_id 130 | left join sys.sysusers ug on ug.uid=p.grantor_principal_id 131 | where class = 1 132 | and u.name = @UserName 133 | order by s.name, o.name 134 | ' 135 | insert into @SqlCommand (SqlText) 136 | execute (@SQL) 137 | if @@rowcount>0 set @CommandExists = 1 138 | 139 | --Если были значимые команды то переносим в результирующую таблицу 140 | if @CommandExists = 1 141 | begin 142 | insert into @SqlCommandResult (SqlText) 143 | select SqlText from @SqlCommand order by Id 144 | end 145 | 146 | fetch next from curDB 147 | into @DatabaseName 148 | end 149 | close curDB 150 | deallocate curDB 151 | select * from @SqlCommandResult 152 | -------------------------------------------------------------------------------- /Tutorial/sql_server/Service Broker/Between Instance/02 Create InitiatorInst.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Создание конечной точки компонента Service Broker 3 | 4 | Чтобы создать конечную точку компонента Service Broker для данного экземпляра компонента 5 | Database Engine. Конечная точка Service Broker указывает сетевой адрес, по которому 6 | направляются сообщения Service Broker. Эта конечная точка использует установленный по 7 | умолчанию компонентом Service Broker порт TCP/IP 4022 и указывает на то, что удаленные 8 | экземпляры Database Engine при отправке сообщений будут использовать средства проверки 9 | подлинности Windows. 10 | 11 | Система проверки подлинности Windows функционирует, когда оба компьютера находятся в одном 12 | и том же домене либо в доверенных доменах. Если компьютеры не расположены в доверенных 13 | доменах, используйте для защиты конечных точек сертификаты безопасности. Дополнительные 14 | сведения см. в разделе Как создать сертификаты для безопасности транспорта компонента 15 | Service Broker (Transact-SQL). 16 | */ 17 | USE master; 18 | GO 19 | IF EXISTS (SELECT * FROM sys.endpoints 20 | WHERE name = N'InstInitiatorEndpoint') 21 | DROP ENDPOINT InstInitiatorEndpoint; 22 | GO 23 | CREATE ENDPOINT InstInitiatorEndpoint 24 | STATE = STARTED 25 | AS TCP ( LISTENER_PORT = 4022 ) 26 | FOR SERVICE_BROKER (AUTHENTICATION = WINDOWS ); 27 | GO 28 | 29 | /** 30 | Создание инициирующей базы данных, главного ключа и пользователя 31 | 32 | Измените пароль в инструкции CREATE MASTER KEY. Затем запустите код для создания 33 | целевой базы данных, которая используется в этом учебнике. По умолчанию в новых 34 | базах данных включен параметр ENABLE_BROKER. Этот код также создает главный ключ 35 | и пользователя, который будет применяться для поддержки шифрования и удаленных соединений. 36 | */ 37 | USE master; 38 | GO 39 | IF EXISTS (SELECT * FROM sys.databases 40 | WHERE name = N'InstInitiatorDB') 41 | DROP DATABASE InstInitiatorDB; 42 | GO 43 | CREATE DATABASE InstInitiatorDB; 44 | GO 45 | ALTER DATABASE InstInitiatorDB SET ENABLE_BROKER 46 | GO 47 | 48 | USE InstInitiatorDB; 49 | GO 50 | 51 | CREATE MASTER KEY 52 | ENCRYPTION BY PASSWORD = N'q1w2e3R$T%Y^'; 53 | GO 54 | CREATE USER InitiatorUser WITHOUT LOGIN; 55 | GO 56 | 57 | /* 58 | Создание сертификата инициатора 59 | 60 | Измените имя файла, указанное в инструкции BACKUP CERTIFICATE, чтобы оно указывало на папку, 61 | расположенную на текущем компьютере. Затем запустите этот код для создания сертификата 62 | инициатора, используемого для шифрования сообщений. В указанной папке должны быть заданы 63 | разрешения, предотвращающие доступ любых учетных записей, кроме учетной записи Windows текущего 64 | пользователя и учетной записи Windows, с которой работает экземпляр компонента Database Engine. 65 | Для занятия 3 вы должны вручную скопировать файл InstInitiatorCertificate.cer в папку, доступную 66 | из целевого экземпляра. 67 | */ 68 | CREATE CERTIFICATE InstInitiatorCertificate 69 | AUTHORIZATION InitiatorUser 70 | WITH SUBJECT = N'Initiator Certificate', 71 | EXPIRY_DATE = N'20151231'; 72 | 73 | BACKUP CERTIFICATE InstInitiatorCertificate 74 | TO FILE = 75 | N'C:\SQL\InstInitiatorCertificate.cer'; 76 | GO 77 | 78 | /* 79 | Создание типов сообщений 80 | 81 | Чтобы создать типы сообщений для диалога. Имена типов сообщений и указанные здесь свойства должны 82 | быть идентичными именам и свойствам, которые были созданы в базе данных InstTargetDB на предыдущем 83 | занятии. 84 | */ 85 | CREATE MESSAGE TYPE [//BothDB/2InstSample/RequestMessage] 86 | VALIDATION = WELL_FORMED_XML; 87 | CREATE MESSAGE TYPE [//BothDB/2InstSample/ReplyMessage] 88 | VALIDATION = WELL_FORMED_XML; 89 | GO 90 | 91 | /* 92 | Создание контракта 93 | 94 | Чтобы создать контракт для диалога. Имя контракта и свойства, указанные здесь, должны быть идентичными 95 | контракту, который вы будете создавать в базе данных InstInitiatorDB на следующем занятии. 96 | */ 97 | CREATE CONTRACT [//BothDB/2InstSample/SimpleContract] 98 | ([//BothDB/2InstSample/RequestMessage] 99 | SENT BY INITIATOR, 100 | [//BothDB/2InstSample/ReplyMessage] 101 | SENT BY TARGET 102 | ); 103 | GO 104 | /* 105 | Создание очереди и службы инициатора 106 | 107 | Чтобы создать очередь и службу, которые будут использоваться для целевой стороны. Инструкция CREATE 108 | SERVICE ассоциирует эту службу с очередью InstInitiatorQueue. Следовательно, все направляемые службе 109 | сообщения будут получены очередью InstInitiatorQueue. Инструкция CREATE SERVICE также указывает, что 110 | использовать службу в качестве целевой могут только диалоги, использующие ранее созданный контракт 111 | //BothDB/2InstSample/SimpleContract. 112 | */ 113 | CREATE QUEUE InstInitiatorQueue; 114 | 115 | CREATE SERVICE [//InstDB/2InstSample/InitiatorService] 116 | AUTHORIZATION InitiatorUser 117 | ON QUEUE InstInitiatorQueue; 118 | GO 119 | 120 | /* 121 | Создание ссылок на целевые объекты 122 | 123 | Измените предложение FROM FILE, поместив в него ссылку на папку, в которую вы скопировали файл 124 | InstTargetCertficate.cer из шага 3 занятия 1. Затем запустите код для создания целевого пользователя 125 | и запросите целевой сертификат. 126 | */ 127 | CREATE USER TargetUser WITHOUT LOGIN; 128 | 129 | CREATE CERTIFICATE InstTargetCertificate 130 | AUTHORIZATION TargetUser 131 | FROM FILE = 132 | N'C:\SQL\InstTargetCertificate.cer' 133 | GO 134 | 135 | /* 136 | Создание маршрутов 137 | 138 | Вместо строки MyTargetComputer введите имя компьютера, на котором выполняется целевой экземпляр. 139 | Затем запустите код для создания маршрутов к целевой службе и к инициирующей службе, а также 140 | привязку удаленной службы, которая ассоциирует пользователя TargetUser с маршрутом к целевой службе. 141 | 142 | В следующих инструкциях CREATE ROUTE предполагается, что в целевом экземпляре отсутствуют повторяющиеся 143 | имена служб. Если несколько баз данных на целевом экземпляре имеют службы с идентичными именами, 144 | используйте предложение BROKER_INSTANCE для указания базы данных, из которой необходимо открыть диалог. 145 | */ 146 | DECLARE @Cmd NVARCHAR(4000); 147 | 148 | SET @Cmd = N'USE InstInitiatorDB; 149 | CREATE ROUTE InstTargetRoute 150 | WITH SERVICE_NAME = 151 | N''//TgtDB/2InstSample/TargetService'', 152 | ADDRESS = N''TCP://SR-SQL-02:4022'';'; 153 | 154 | EXEC (@Cmd); 155 | 156 | SET @Cmd = N'USE msdb 157 | CREATE ROUTE InstInitiatorRoute 158 | WITH SERVICE_NAME = 159 | N''//InstDB/2InstSample/InitiatorService'', 160 | ADDRESS = N''LOCAL'''; 161 | 162 | EXEC (@Cmd); 163 | GO 164 | CREATE REMOTE SERVICE BINDING TargetBinding 165 | TO SERVICE 166 | N'//TgtDB/2InstSample/TargetService' 167 | WITH USER = TargetUser; 168 | 169 | GO 170 | 171 | -------------------------------------------------------------------------------- /SQL Server/clr/account/AccountChecksum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text.RegularExpressions; 4 | 5 | public static class AccountChecksum 6 | { 7 | #region privates 8 | private static bool IsBic(string bic) 9 | { 10 | // simply check if it's not empty 11 | if (String.IsNullOrWhiteSpace(bic)) return false; 12 | 13 | // all symbols are digits 14 | if (!m_AllDigits.IsMatch(bic)) return false; 15 | 16 | // must be 9 symbols long 17 | if (bic.Length != 9) return false; 18 | 19 | return true; 20 | } 21 | private static string Unmask(string mask, int num) 22 | { 23 | if (string.IsNullOrWhiteSpace(mask)) return null; 24 | mask = mask.ToLower(); 25 | if (!mask.Contains("x")) return mask; 26 | 27 | var masked = string.Format("{0:00000000000000000000}", num); 28 | 29 | var j = masked.Length - 1; 30 | var sb = mask.ToCharArray(); 31 | for (var i = sb.Length - 1; i >= 0; i--) 32 | { 33 | if (j > 0 && mask[i] == 'x') 34 | { 35 | sb[i] = masked[j]; 36 | j--; 37 | } 38 | } 39 | return string.Join("", sb); 40 | } 41 | private static readonly Regex m_AllDigits = new Regex(@"^\d+$", RegexOptions.Compiled); 42 | private static readonly int[] m_WeightsForAccountNumber = new int[23] { 7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1 }; 43 | private static readonly int[] m_WeightsForInn = new int[12] { 3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0 }; 44 | private static readonly char[] m_AllowedCodesForDigit6 = new char[10] { 'A', 'B', 'C', 'E', 'H', 'K', 'M', 'P', 'T', 'X' }; 45 | private static readonly int[] m_Deltas = new[] { 0, 1, 2, 3, 4, -4, -3, -2, -1, 0 }; 46 | private static string digitizeAccountNumber(string accountNumber) 47 | { 48 | // substitute allowed alphabet symbols 49 | char possibleSymbol = accountNumber[5]; 50 | int index = Array.IndexOf(m_AllowedCodesForDigit6, possibleSymbol); 51 | if (index != -1) 52 | { 53 | accountNumber = accountNumber.Substring(0, 5) + Convert.ToString(index) + accountNumber.Substring(6, 14); 54 | } 55 | return accountNumber; 56 | } 57 | private static int[] calculateWeightedProducts(string accountNumber, string bic, bool bicIsRkc) 58 | { 59 | var result = new int[23]; 60 | if (!bicIsRkc) 61 | { 62 | for (int i = 0; i < 3; i++) 63 | { 64 | result[i] = ((bic[i + 6] - 48) * m_WeightsForAccountNumber[i]) % 10; 65 | } 66 | } 67 | else 68 | { 69 | result[0] = 0; 70 | result[1] = ((bic[4] - 48) * m_WeightsForAccountNumber[1]) % 10; 71 | result[2] = ((bic[5] - 48) * m_WeightsForAccountNumber[2]) % 10; 72 | } 73 | 74 | for (int i = 0; i < 20; i++) 75 | { 76 | result[i + 3] = ((accountNumber[i] - 48) * m_WeightsForAccountNumber[i]) % 10; 77 | } 78 | return result; 79 | } 80 | #endregion 81 | 82 | [Microsoft.SqlServer.Server.SqlFunction] 83 | public static string UnmaskBankAccount(string mask, string bic, int num) 84 | { 85 | if (string.IsNullOrWhiteSpace(mask)) return ""; 86 | if (string.IsNullOrWhiteSpace(bic)) return ""; 87 | 88 | var accountNumber = Unmask(mask, num); 89 | if (!IsBic(bic)) throw new ArgumentOutOfRangeException("bic", "Please provide valid BIC"); 90 | var checksum = CalculateAccountChecksum(accountNumber, bic); 91 | return accountNumber.Remove(8, 1).Insert(8, string.Format("{0:0}", checksum)); 92 | } 93 | /// 94 | /// Calculate account checksum for provided account number and bic 95 | /// ПОРЯДОК РАСЧЕТА КОНТРОЛЬНОГО КЛЮЧА В НОМЕРЕ ЛИЦЕВОГО СЧЕТА (ЦЕНТРАЛЬНЫЙ БАНК РОССИИ, 8 сентября 1997 г. N 515) 96 | /// 97 | /// Номер лицевого счета 98 | /// БИК - Банковский Идентификационный Код 99 | /// true, если БИК принадлежит РКЦ (Расчетно-Кассовому Центру), иначе false. По умолчанию false 100 | /// true if valid, false otherwise 101 | [Microsoft.SqlServer.Server.SqlFunction] 102 | public static int CalculateAccountChecksum(string accountNumber, string bic, bool bicIsRkc = false) 103 | { 104 | // simply check if it's not empty 105 | if (String.IsNullOrWhiteSpace(accountNumber)) throw new ArgumentOutOfRangeException("accountNumber", "Account number can not be empty"); 106 | // must be 20 symbols long 107 | if (accountNumber.Length != 20) throw new ArgumentOutOfRangeException("accountNumber", "Account number must be of length 20"); ; 108 | // validate bic 109 | if (!IsBic(bic)) throw new ArgumentOutOfRangeException("bic", "Please provide valid BIC"); 110 | accountNumber = digitizeAccountNumber(accountNumber); 111 | // all symbols are digits now 112 | if (!m_AllDigits.IsMatch(accountNumber)) throw new ArgumentOutOfRangeException("accountNumber", "Account number must be valid account number"); 113 | 114 | var p = calculateWeightedProducts(accountNumber, bic, bicIsRkc); 115 | p[11] = 0; 116 | return ((p.Sum() % 10) * 3) % 10; 117 | } 118 | /// 119 | /// Check is the string is a valid account number according to 120 | /// ПОРЯДОК РАСЧЕТА КОНТРОЛЬНОГО КЛЮЧА В НОМЕРЕ ЛИЦЕВОГО СЧЕТА (ЦЕНТРАЛЬНЫЙ БАНК РОССИИ, 8 сентября 1997 г. N 515) 121 | /// 122 | /// Номер лицевого счета 123 | /// БИК - Банковский Идентификационный Код 124 | /// true, если БИК принадлежит РКЦ (Расчетно-Кассовому Центру), иначе false. По умолчанию false 125 | /// true if valid, false otherwise 126 | [Microsoft.SqlServer.Server.SqlFunction] 127 | public static bool IsValidAccountNumber(string accountNumber, string bic, bool bicIsRkc = false) 128 | { 129 | // simply check if it's not empty 130 | if (String.IsNullOrWhiteSpace(accountNumber)) return false; 131 | // validate bic 132 | if (!IsBic(bic)) return false; 133 | // must be 20 symbols long 134 | if (accountNumber.Length != 20) return false; 135 | 136 | accountNumber = digitizeAccountNumber(accountNumber); 137 | // all symbols are digits now 138 | if (!m_AllDigits.IsMatch(accountNumber)) return false; 139 | 140 | // calculate weighted products 141 | var p = calculateWeightedProducts(accountNumber, bic, bicIsRkc); 142 | 143 | // calculate checksum 144 | // p[11] = 0; 145 | // var checksum = ((p.Sum() %10)*3) %10; 146 | 147 | // verify checksum 148 | // p[11] = (checksum * m_Weights[11]) %10; 149 | 150 | int verify = p.Sum() % 10; 151 | return (verify == 0); 152 | } 153 | } 154 | 155 | -------------------------------------------------------------------------------- /PostgreSQL/account/README.md: -------------------------------------------------------------------------------- 1 | ### Установка в PostgreSQL 2 | 3 | Аналогично установке в SQL Server, где мы использовали CLR-сборку, в PostgreSQL мы создадим функции напрямую с помощью PL/pgSQL. Это не требует компиляции или внешних DLL — функции регистрируются в базе данных как хранимые процедуры. Вам понадобится доступ администратора для создания расширений и функций. 4 | 5 | #### Шаги установки 6 | 1. **Подключитесь к PostgreSQL**: Используйте psql, pgAdmin или любой клиент. 7 | 2. **Включите PL/pgSQL** (если не включено): Выполните `CREATE EXTENSION IF NOT EXISTS plpgsql;`. 8 | 3. **Выполните скрипт ниже**: Он создаст все функции. Функции помечены как `IMMUTABLE` для оптимизации (кеширования результатов). 9 | 4. **Тестируйте**: После создания вызовите функции, как в примерах. 10 | 11 | #### SQL-скрипт для создания функций 12 | 13 | ```sql 14 | -- Включение PL/pgSQL (если не включено) 15 | CREATE EXTENSION IF NOT EXISTS plpgsql; 16 | 17 | -- Функция для проверки BIC (аналог IsBic) 18 | CREATE OR REPLACE FUNCTION is_bic_valid(bic TEXT) 19 | RETURNS BOOLEAN AS $$ 20 | BEGIN 21 | IF bic IS NULL OR LENGTH(TRIM(bic)) <> 9 OR bic !~ '^[0-9]+$' THEN 22 | RETURN FALSE; 23 | END IF; 24 | RETURN TRUE; 25 | END; 26 | $$ LANGUAGE plpgsql IMMUTABLE; 27 | 28 | -- Функция для цифровизации номера счета (аналог digitizeAccountNumber) 29 | CREATE OR REPLACE FUNCTION digitize_account_number(account_number TEXT) 30 | RETURNS TEXT AS $$ 31 | DECLARE 32 | result TEXT := ''; 33 | char_val TEXT; 34 | digit_map CONSTANT TEXT[] := ARRAY['0','1','2','3','4','5','6','7','8','9']; -- A=0, B=1, ..., X=9 35 | idx INT; 36 | BEGIN 37 | IF LENGTH(account_number) <> 20 THEN 38 | RAISE EXCEPTION 'Account number must be 20 characters'; 39 | END IF; 40 | FOR i IN 1..20 LOOP 41 | char_val := SUBSTRING(account_number, i, 1); 42 | IF i = 6 THEN 43 | -- Замена буквы на цифру 44 | idx := POSITION(UPPER(char_val) IN 'ABCEHKMPTX'); 45 | IF idx > 0 THEN 46 | result := result || digit_map[idx]; 47 | ELSIF char_val ~ '^[0-9]$' THEN 48 | result := result || char_val; 49 | ELSE 50 | RAISE EXCEPTION 'Invalid character at position 6'; 51 | END IF; 52 | ELSE 53 | IF char_val ~ '^[0-9]$' THEN 54 | result := result || char_val; 55 | ELSE 56 | RAISE EXCEPTION 'Account number must contain only digits except position 6'; 57 | END IF; 58 | END IF; 59 | END LOOP; 60 | RETURN result; 61 | END; 62 | $$ LANGUAGE plpgsql IMMUTABLE; 63 | 64 | -- Функция для расчета контрольной суммы (аналог CalculateAccountChecksum) 65 | CREATE OR REPLACE FUNCTION calculate_account_checksum(account_number TEXT, bic TEXT, bic_is_rkc BOOLEAN DEFAULT FALSE) 66 | RETURNS INTEGER AS $$ 67 | DECLARE 68 | digitized TEXT; 69 | weights CONSTANT INTEGER[] := ARRAY[ 70 | 7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1 71 | ]; -- 23 веса 72 | products INTEGER[] := ARRAY[]::INTEGER[]; 73 | sum_val INTEGER := 0; 74 | bic_part TEXT; 75 | i INT; 76 | BEGIN 77 | IF NOT is_bic_valid(bic) THEN 78 | RAISE EXCEPTION 'Invalid BIC'; 79 | END IF; 80 | digitized := digitize_account_number(account_number); 81 | IF bic_is_rkc THEN 82 | bic_part := SUBSTRING(bic, 5, 2); 83 | ELSE 84 | bic_part := SUBSTRING(bic, 7, 3); 85 | END IF; 86 | -- Строим массив для расчета 87 | FOR i IN 1..23 LOOP 88 | IF i <= 3 THEN 89 | products[i] := (SUBSTRING(bic_part, i, 1)::INTEGER) * weights[i]; 90 | ELSIF i >= 4 AND i <= 23 THEN 91 | products[i] := (SUBSTRING(digitized, i-3, 1)::INTEGER) * weights[i]; 92 | END IF; 93 | sum_val := sum_val + products[i]; 94 | END LOOP; 95 | RETURN ((sum_val % 10) * 3) % 10; 96 | END; 97 | $$ LANGUAGE plpgsql IMMUTABLE; 98 | 99 | -- Функция для раскрытия маски с вставкой checksum (аналог UnmaskBankAccount) 100 | CREATE OR REPLACE FUNCTION unmask_bank_account(mask TEXT, bic TEXT, num INTEGER) 101 | RETURNS TEXT AS $$ 102 | DECLARE 103 | unmasked TEXT := ''; 104 | num_str TEXT := LPAD(num::TEXT, 20, '0'); -- Форматируем num до 20 цифр 105 | checksum INTEGER; 106 | temp_account TEXT; 107 | i INT; 108 | x_count INT := 0; 109 | BEGIN 110 | IF mask IS NULL OR LENGTH(mask) <> 20 THEN 111 | RAISE EXCEPTION 'Mask must be 20 characters'; 112 | END IF; 113 | -- Считаем 'x' и заменяем с конца 114 | FOR i IN REVERSE 1..20 LOOP 115 | IF SUBSTRING(mask, i, 1) = 'x' THEN 116 | x_count := x_count + 1; 117 | unmasked := SUBSTRING(num_str, 21 - x_count, 1) || unmasked; 118 | ELSE 119 | unmasked := SUBSTRING(mask, i, 1) || unmasked; 120 | END IF; 121 | END LOOP; 122 | -- Рассчитываем checksum и вставляем в 9-ю позицию (заменяя 8-й символ, как в оригинале) 123 | checksum := calculate_account_checksum(unmasked, bic); 124 | temp_account := SUBSTRING(unmasked, 1, 7) || checksum::TEXT || SUBSTRING(unmasked, 9); 125 | RETURN temp_account; 126 | END; 127 | $$ LANGUAGE plpgsql IMMUTABLE; 128 | 129 | -- Функция для проверки валидности (аналог IsValidAccountNumber) 130 | CREATE OR REPLACE FUNCTION is_valid_account_number(account_number TEXT, bic TEXT, bic_is_rkc BOOLEAN DEFAULT FALSE) 131 | RETURNS BOOLEAN AS $$ 132 | DECLARE 133 | digitized TEXT; 134 | weights CONSTANT INTEGER[] := ARRAY[ 135 | 7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1,3,7,1 136 | ]; 137 | products INTEGER[] := ARRAY[]::INTEGER[]; 138 | sum_val INTEGER := 0; 139 | bic_part TEXT; 140 | i INT; 141 | BEGIN 142 | IF NOT is_bic_valid(bic) THEN 143 | RETURN FALSE; 144 | END IF; 145 | digitized := digitize_account_number(account_number); 146 | IF bic_is_rkc THEN 147 | bic_part := SUBSTRING(bic, 5, 2); 148 | ELSE 149 | bic_part := SUBSTRING(bic, 7, 3); 150 | END IF; 151 | FOR i IN 1..23 LOOP 152 | IF i <= 3 THEN 153 | products[i] := (SUBSTRING(bic_part, i, 1)::INTEGER) * weights[i]; 154 | ELSIF i >= 4 AND i <= 23 THEN 155 | products[i] := (SUBSTRING(digitized, i-3, 1)::INTEGER) * weights[i]; 156 | END IF; 157 | sum_val := sum_val + products[i]; 158 | END LOOP; 159 | RETURN (sum_val % 10) = 0; 160 | END; 161 | $$ LANGUAGE plpgsql IMMUTABLE; 162 | ``` 163 | 164 | #### Примеры использования после установки 165 | - Проверка BIC: `SELECT is_bic_valid('044525225');` → `true` 166 | - Расчет checksum: `SELECT calculate_account_checksum('12345678901234567890', '044525225');` → `5` (пример; зависит от входа) 167 | - Раскрытие маски: `SELECT unmask_bank_account('12345x78x01234567890', '044525225', 123456789);` → Полный счет с вставленным checksum 168 | - Валидация: `SELECT is_valid_account_number('12345678901234567890', '044525225');` → `true` или `false` 169 | 170 | Если возникнут ошибки (например, из-за версий PostgreSQL), проверьте логи сервера. Для дальнейших оптимизаций (например, индексы или C-расширение) уточните. Функции адаптированы для соответствия алгоритму ЦБ РФ и оригинальному C#-классу. -------------------------------------------------------------------------------- /SQL Server/diagnostics/Тяжелые запросы.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Получаемые столбцы: 3 | 4 | creation_time — Время, когда запрос был скомпилирован. Поскольку при старте сервера кэш пустой, данное время всегда больше либо равно моменту запуска сервиса. Если время, указанное в этом столбце позже, чем предполагаемое (первое использование процедуры), это говорит о том, что запрос по тем или иным причинам был рекомпилирован. 5 | last_execution_time — Момент фактического последнего выполнения запроса. 6 | execution_count — Сколько раз запрос был выполнен с момента компиляции 7 | Количество выполнений позволяет найти ошибки в алгоритмах — часто в наиболее выполняемых запросах оказываются те, которые находятся внутри каких-либо циклов однако могут быть выполнены перед самим циклом один раз. Например, получение каких-либо параметров из базы данных, не меняющихся внутри цикла. 8 | CPU — Суммарное время использования процессора в миллисекундах. Если запрос обрабатывается параллельно, то это время может превысить общее время выполнения запроса, поскольку суммируется время использования запроса каждым ядром. Во время использования процессора включается только фактическая нагрузка на ядра, в нее не входят ожидания каких-либо ресурсов. 9 | Очевидно, что данный показатель позволяет выявлять запросы, наиболее сильно загружающие процессор. 10 | AvgCPUTime — Средняя загрузка процессора на один запрос. 11 | TotDuration — Общее время выполнения запроса, в миллисекундах. 12 | Данный параметр может быть использован для поиска тех запросов, которые, независимо от причины выполняются «наиболее долго». Если общее время выполнения запроса существенно ниже времени CPU (с поправкой на параллелизм) — это говорит о том, что при выполнения запроса были ожидания каких-либо ресурсов. В большинстве случаев это связано с дисковой активностью или блокировками, но также это может быть сетевой интерфейс или другой ресурс. 13 | Полный список типов ожиданий можно посмотреть в описании представления sys.dm_os_wait_stats. 14 | AvgDur — Среднее время выполнения запроса в миллисекундах. 15 | Reads — Общее количество чтений. 16 | Это пожалуй лучший агрегатный показатель, позволяющий выявить наиболее нагружающие сервер запросы. 17 | Логическое чтение — это разовое обращение к странице данных, физические чтения не учитываются. 18 | В рамках выполнения одного запроса, могут происходить неоднократные обращения к одной и той же странице. 19 | Чем больше обращений к страницам, тем больше требуется дисковых чтений, памяти и, если речь идет о повторных обращениях, большее время требуется удерживать страницы в памяти. 20 | Writes — Общее количество изменений страниц данных. 21 | Характеризует то, как запрос «нагружает» дисковую систему операциями записи. 22 | Следует помнить, что этот показатель может быть больше 0 не только у тех запросов, которые явно меняют данные, но также и у тех, которые сохраняют промежуточные данные в tempdb. 23 | AggIO — Общее количество логических операций ввода-вывода (суммарно) 24 | Как правило, количество логических чтений на порядки превышает количество операций записи, поэтому этот показатель сам по себе для анализа применим в редких случаях. 25 | AvgIO — Среднее количество логических дисковых операций на одно выполнение запроса. 26 | Значение данного показателя можно анализировать из следующих соображений: 27 | Одна страница данных — это 8192 байта. Можно получить среднее количество байт данных, «обрабатываемых» данным запросом. Если этот объем превышает реальное количество данных, которые обрабатывает запрос (суммарный объем данных в используемых в запросе таблицах), это говорит о том, что был выбран заведомо плохой план выполнения и требуется заняться оптимизацией данного запроса. 28 | Я встречал случай, когда один запрос делал количество обращений, эквивалентных объему в 5Тб, при этом общий объем данных в это БД был 300Гб, а объем данных в таблицах, задействованных в запросе не превышал 10Гб. 29 | В общем можно описать одну причину такого поведения сервера — вместо использования индекса сервер предпочитает сканировать таблицу или наоборот. 30 | Если объем логических чтений в разы превосходит общие объем данных, то это вызвано повторным обращениям к одним и тем же страницам данных. Помимо того, что в одном запросе таблица может быть использована несколько раз, к одним и тем же страницам сервер обращается например в случаях, когда используется индекс и по результатам поиска по нему, найденные некоторые строки данных лежат на одной и той же странице. Конечно, в таком случае предпочтительным могло бы быть сканирование таблицы — в этом случае сервер обращался бы к каждой странице данных только один раз. Однако этому часто мешают… попытки оптимизации запросов, когда разработчик явно указывает, какой индекс или тип соединения должен быть использован. 31 | Обратный случай — вместо использования индекса было выбрано сканирование таблицы. Как правило, это связано с тем, что статистикаустарела и требуется её обновление. Однако и в этом случае причиной неудачно выбранного плана вполне могут оказаться подсказки оптимизатору запросов. 32 | query_text — Текст самого запроса 33 | database_name — Имя базы данных, в находится объект, содержащий запрос. NULL для системных процедур 34 | object_name — Имя объекта (процедуры или функции), содержащего запрос. 35 | query_plan — План запроса. Достаточно щёлкнуть по выводу и в новом окне откроется план запроса. Для пользователей SQL Server 2005 есть особенности (см. ниже) 36 | 37 | Используя разные варианты сортировки, можно искать запросы, которые более всего расходуют процессорный ресурс, имеют самое долгое время выполнения (как в примере и т.д.) 38 | Конечно, также можно фильтровать объекты по базе данных и/или имени объекта. 39 | Однако в любом случае следует помнить, что данная статистика относится только к тем запросам, которые сохранены в процедурном кэше сервера. Если по каким-либо причинам (нехватка памяти, неявная рекомпиляция запросов или явные команды) 40 | */ 41 | 42 | SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; 43 | SELECT TOP 100 44 | creation_time , 45 | last_execution_time , 46 | execution_count , 47 | total_worker_time / 1000 AS CPU , 48 | CONVERT(MONEY, ( total_worker_time )) / ( execution_count * 1000 ) AS [AvgCPUTime] , 49 | qs.total_elapsed_time / 1000 AS TotDuration , 50 | CONVERT(MONEY, ( qs.total_elapsed_time )) / ( execution_count * 1000 ) AS [AvgDur] , 51 | total_logical_reads AS [Reads] , 52 | total_logical_writes AS [Writes] , 53 | total_logical_reads + total_logical_writes AS [AggIO] , 54 | CONVERT(MONEY, ( total_logical_reads + total_logical_writes ) 55 | / ( execution_count + 0.0 )) AS [AvgIO] , 56 | CASE WHEN sql_handle IS NULL THEN ' ' 57 | ELSE ( SUBSTRING(st.text, ( qs.statement_start_offset + 2 ) / 2, 58 | ( CASE WHEN qs.statement_end_offset = -1 59 | THEN LEN(CONVERT(NVARCHAR(MAX), st.text)) * 2 60 | ELSE qs.statement_end_offset 61 | END - qs.statement_start_offset ) / 2) ) 62 | END AS query_text , 63 | DB_NAME(st.dbid) AS database_name , 64 | OBJECT_SCHEMA_NAME(st.objectid, st.dbid) + '.' + OBJECT_NAME(st.objectid, 65 | st.dbid) AS object_name 66 | FROM 67 | sys.dm_exec_query_stats qs 68 | CROSS APPLY sys.dm_exec_sql_text(sql_handle) st 69 | WHERE 70 | total_logical_reads > 0 71 | ORDER BY 72 | AvgDur DESC; -------------------------------------------------------------------------------- /SQL Server/clr/invalid_objects/InvalidObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data.SqlTypes; 3 | using System.Data.SqlClient; 4 | using System.Data; 5 | using Microsoft.SqlServer.Server; 6 | using System.Security.Principal; 7 | 8 | public class InvalidObjects 9 | { 10 | [SqlFunction(DataAccess = DataAccessKind.Read, SystemDataAccess = SystemDataAccessKind.Read, IsDeterministic=false)] 11 | public static SqlString GetInvalidObjectInfo(int object_id,string dbName, string serverName) 12 | { 13 | string ObjectName = null; 14 | string ObjectType = null; 15 | const string SetShowPlanOn = "SET SHOWPLAN_XML ON"; 16 | string CheckSQL = ""; 17 | 18 | SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(); 19 | 20 | if (string.IsNullOrEmpty(serverName)) 21 | { 22 | using (SqlConnection sql_conn = new SqlConnection("context connection=true")) 23 | { 24 | SqlCommand sql_cmd = sql_conn.CreateCommand(); 25 | sql_cmd.CommandText = "select serverproperty('ComputerNamePhysicalNetBIOS') as ServerName, serverproperty('InstanceName') as InstanceName"; 26 | try 27 | { 28 | sql_conn.Open(); 29 | using (SqlDataReader dr = sql_cmd.ExecuteReader(CommandBehavior.CloseConnection)) 30 | { 31 | if (dr.Read()) 32 | { 33 | if (dr["InstanceName"] == DBNull.Value) 34 | sb.DataSource = Convert.ToString(dr["ServerName"]); 35 | else 36 | sb.DataSource = string.Format(@"{0}\{1}", Convert.ToString(dr["ServerName"]), Convert.ToString(dr["InstanceName"])); 37 | sb.InitialCatalog = dbName; 38 | sb.IntegratedSecurity = true; 39 | sb.ApplicationName = "CLR Invalid object checker."; 40 | } 41 | dr.Close(); 42 | } 43 | 44 | } 45 | catch (Exception ex) 46 | { 47 | return ex.Message.ToString(); 48 | } 49 | } 50 | } 51 | else 52 | { 53 | sb.DataSource = serverName; 54 | sb.InitialCatalog = dbName; 55 | sb.IntegratedSecurity = true; 56 | sb.ApplicationName = "CLR Invalid object checker."; 57 | } 58 | 59 | using (SqlConnection sql_con = new SqlConnection(sb.ToString())) 60 | { 61 | sql_con.Open(); 62 | using (SqlCommand sql_cmd = sql_con.CreateCommand()) 63 | { 64 | sql_cmd.CommandText = "select quotename(schema_name(schema_id))+'.'+quotename([name]) as fullname, " + 65 | "rtrim([type]) as [type] from sys.all_objects where object_id = @oid"; 66 | sql_cmd.Parameters.Add("@oid", SqlDbType.Int).Value = object_id; 67 | try 68 | { 69 | using (SqlDataReader dr = sql_cmd.ExecuteReader()) 70 | { 71 | if (dr.Read()) 72 | { 73 | ObjectName = Convert.ToString(dr[0]); 74 | ObjectType = Convert.ToString(dr[1]); 75 | } 76 | else 77 | return string.Format("Not found this object_id: {0}", object_id.ToString()); 78 | } 79 | } 80 | catch (Exception ex) 81 | { 82 | return ex.Message; 83 | } 84 | } 85 | 86 | switch (ObjectType) 87 | { 88 | case "V": 89 | CheckSQL = "select * from " + ObjectName; 90 | break; 91 | case "P": 92 | CheckSQL = ObjectName; 93 | break; 94 | case "FN": 95 | CheckSQL = ObjectName; 96 | break; 97 | case "IF": 98 | case "TF": 99 | using (SqlCommand sql_cmd = new SqlCommand("declare @s varchar(255) set @s = '' " + 100 | "select @s = @s+', '+ case type_name(p.user_type_id) " + 101 | "when 'uniqueidentifier' then '''00000000-0000-0000-0000-000000000000''' " + 102 | "when 'int' then '0' " + 103 | "when 'varchar' then '''varchar''' " + 104 | "when 'datetime' then '''19000101''' " + 105 | "when 'sysname' then '''sysname''' " + 106 | "when 'image' then master.sys.fn_varbintohexstr( CAST( 123456 AS BINARY(4))) " + 107 | "when 'xml' then '''''' " + 108 | "when 'sql_variant' then '''sql_variant''' " + 109 | "when 'money' then '0' " + 110 | "when 'decimal' then '0' " + 111 | "when 'timestamp' then master.sys.fn_varbintohexstr( @@DBTS) " + 112 | "when 'varbinary' then master.sys.fn_varbintohexstr( CAST( 123456 AS BINARY(4))) " + 113 | "when 'text' then master.sys.fn_varbintohexstr( CAST( 123456 AS BINARY(4))) " + 114 | "when 'smallint' then '0' " + 115 | "when 'binary' then master.sys.fn_varbintohexstr( CAST( 123456 AS BINARY(4))) " + 116 | "when 'numeric' then '0' " + 117 | "when 'tinyint' then '0' " + 118 | "when 'nchar' then '''nchar''' " + 119 | "when 'float' then '0' " + 120 | "when 'char' then '''char''' " + 121 | "when 'real' then '0' " + 122 | "when 'bigint' then '0' " + 123 | "when 'ntext' then master.sys.fn_varbintohexstr( CAST( 123456 AS BINARY(4))) " + 124 | "when 'nvarchar' then 'N''nvarchar''' " + 125 | "when 'bit' then '0' end " + 126 | "from sys.parameters p where object_id = @oid " + 127 | "and default_value is null " + 128 | "order by p.parameter_id " + 129 | "select @s = case when len(@s)>0 then substring(@s, 3, len(@s)-2) else @s end " + 130 | "select @s", sql_con)) 131 | { 132 | sql_cmd.Parameters.Add("@oid", SqlDbType.Int).Value = object_id; 133 | 134 | using (SqlDataReader dr = sql_cmd.ExecuteReader(CommandBehavior.SingleRow)) 135 | { 136 | if (dr.Read()) 137 | { 138 | CheckSQL = string.Format("select * from {0}({1})", ObjectName, Convert.ToString(dr[0])); 139 | } 140 | else 141 | CheckSQL = string.Format("select * from {0}()", ObjectName); 142 | } 143 | } 144 | break; 145 | 146 | default: 147 | return "Not support type('" + ObjectType + "')"; 148 | 149 | } 150 | 151 | using (SqlCommand sql_cmd = sql_con.CreateCommand()) 152 | { 153 | sql_cmd.CommandTimeout = 3600; 154 | try 155 | { 156 | if (ObjectType != "TF") 157 | { 158 | sql_cmd.CommandText = SetShowPlanOn; 159 | sql_cmd.ExecuteNonQuery(); 160 | } 161 | 162 | sql_cmd.CommandText = CheckSQL; 163 | sql_cmd.ExecuteNonQuery(); 164 | return SqlString.Null; 165 | } 166 | catch (Exception ex) 167 | { 168 | return ex.Message; 169 | } 170 | } 171 | } // end using SqlConnection 172 | } // end function 173 | } 174 | 175 | -------------------------------------------------------------------------------- /SQL Server/maintenance/SmartShrink2.sql: -------------------------------------------------------------------------------- 1 | IF OBJECT_ID(N'msdb.dbo.SmartShrink',N'U') IS NULL 2 | CREATE TABLE msdb.dbo.SmartShrink( 3 | spid INT NOT NULL DEFAULT (@@SPID), 4 | ObjectName NVARCHAR(513) NOT NULL, 5 | QueryCrtIndex NVARCHAR(MAX) NOT NULL, 6 | QueryDrpIndex NVARCHAR(MAX) NOT NULL, 7 | StartCreate DATETIME NULL, 8 | EndCreate DATETIME NULL, 9 | StartDrop DATETIME NULL, 10 | EndDrop DATETIME NULL, 11 | CONSTRAINT PK_SmartShrink PRIMARY KEY CLUSTERED (spid,ObjectName) 12 | ); 13 | GO 14 | IF OBJECT_ID(N'msdb.dbo.SmartShrinkParams',N'U') IS NULL 15 | CREATE TABLE msdb.dbo.SmartShrinkParams( 16 | spid INT NOT NULL DEFAULT (@@SPID), 17 | GetIndex TINYINT NOT NULL DEFAULT(0), 18 | CreateIndex BIT NOT NULL DEFAULT(0), 19 | ShrinkFile BIT NOT NULL DEFAULT(0), 20 | DropIndex BIT NOT NULL DEFAULT(0), 21 | CONSTRAINT PK_SmartShrinkParams PRIMARY KEY CLUSTERED (spid) 22 | ); 23 | GO 24 | IF OBJECT_ID(N'msdb.dbo.SmartShrinkLog',N'U') IS NULL BEGIN 25 | CREATE TABLE msdb.dbo.SmartShrinkLog( 26 | TimeIns DATETIME2 NOT NULL DEFAULT(SYSDATETIME()), 27 | MsgText VARCHAR(1000) NOT NULL, 28 | QueryText VARCHAR(MAX) NULL, 29 | SPID INT NOT NULL DEFAULT(@@SPID) 30 | ); 31 | CREATE CLUSTERED INDEX ixSmartShrinkLog 32 | ON msdb.dbo.SmartShrinkLog(TimeIns,SPID) 33 | END 34 | GO 35 | IF OBJECT_ID ('tempdb..#GetIndex','P') IS NOT NULL 36 | drop PROCEDURE #GetIndex; 37 | GO 38 | CREATE PROCEDURE #GetIndex(@spid INT,@TableSpace sysname = NULL) 39 | AS 40 | BEGIN 41 | --  уча обычна¤ 42 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText) VALUES('#SmartShrink.#GetData: index get start.'); 43 | 44 | DELETE FROM msdb.dbo.SmartShrink WHERE spid = @spid; 45 | 46 | INSERT INTO msdb.dbo.SmartShrink( ObjectName ,QueryCrtIndex ,QueryDrpIndex ) 47 | SELECT 48 | QUOTENAME(SCHEMA_NAME(tbl.schema_id))+'.'+QUOTENAME(tbl.name) 49 | ,N'USE '+QUOTENAME(DB_NAME())+'; 50 | '+N'CREATE CLUSTERED INDEX [clidxtmp_'+tbl.name+N'] ON '+QUOTENAME(SCHEMA_NAME(tbl.schema_id))+N'.'+QUOTENAME(tbl.name)+ N' ('+col.name+N')' 51 | ,N'USE '+QUOTENAME(DB_NAME())+'; 52 | '+N'DROP INDEX [clidxtmp_'+tbl.name+N'] ON '+QUOTENAME(SCHEMA_NAME(tbl.schema_id))+N'.'+QUOTENAME(tbl.name) 53 | FROM sys.tables tbl 54 | INNER JOIN sys.indexes idx ON idx.object_id = tbl.object_id AND idx.index_id = 0 55 | INNER JOIN sys.columns col ON col.object_id = tbl.object_id AND col.column_id = 1 56 | JOIN sys.data_spaces ds ON ds.data_space_id = idx.data_space_id 57 | inner join sys.filegroups as fg on fg.data_space_id = ds.data_space_id 58 | WHERE SCHEMA_NAME(tbl.schema_id) NOT IN ('sys') AND ds.type = 'FG' 59 | AND (fg.name = @TableSpace OR @TableSpace IS NULL); 60 | 61 | --  уча секционированна¤ 62 | INSERT INTO msdb.dbo.SmartShrink( ObjectName ,QueryCrtIndex ,QueryDrpIndex ) 63 | SELECT DISTINCT QUOTENAME(SCHEMA_NAME(tbl.schema_id))+'.'+QUOTENAME(tbl.name) 64 | ,N'USE '+QUOTENAME(DB_NAME())+'; 65 | '+N'CREATE CLUSTERED INDEX [clidxtmp_'+tbl.name+N'] ON '+QUOTENAME(SCHEMA_NAME(tbl.schema_id))+N'.'+QUOTENAME(tbl.name)+ N' ('+c.name+N') ON '+ds.name+N' ('+c.name+N')' 66 | ,N'USE '+QUOTENAME(DB_NAME())+'; 67 | '+N'DROP INDEX [clidxtmp_'+tbl.name+N'] ON '+QUOTENAME(SCHEMA_NAME(tbl.schema_id))+N'.'+QUOTENAME(tbl.name) 68 | from sys.tables tbl 69 | join sys.indexes idx ON(idx.object_id = tbl.object_id and idx.index_id = 0) 70 | join sys.index_columns ic on(ic.partition_ordinal > 0 and ic.index_id = idx.index_id and ic.object_id = tbl.object_id) 71 | join sys.columns c on(c.object_id = ic.object_id and c.column_id = ic.column_id) 72 | JOIN sys.data_spaces ds ON ds.data_space_id = idx.data_space_id 73 | JOIN sys.partitions p ON p.object_id = tbl.object_id 74 | JOIN sys.allocation_units au ON au.container_id = p.hobt_id 75 | JOIN sys.filegroups fg ON fg.data_space_id = au.data_space_id 76 | WHERE (fg.name = @TableSpace OR @TableSpace IS NULL) 77 | 78 | UPDATE msdb.dbo.SmartShrinkParams SET GetIndex = 1 WHERE spid = @spid; 79 | 80 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText) VALUES('#SmartShrink.#GetData: index get finish.'); 81 | END 82 | GO 83 | IF OBJECT_ID ('tempdb..#CreateIndex','P') IS NOT NULL 84 | DROP PROCEDURE #CreateIndex; 85 | GO 86 | CREATE PROCEDURE #CreateIndex (@spid INT) 87 | AS 88 | BEGIN 89 | DECLARE @ObjName NVARCHAR(513), @QueryExec NVARCHAR(MAX); 90 | DECLARE curCreate CURSOR FOR SELECT ObjectName,QueryCrtIndex FROM msdb.dbo.SmartShrink WHERE spid = @spid AND EndCreate IS NULL; 91 | 92 | BEGIN TRY 93 | OPEN curCreate; 94 | FETCH NEXT FROM curCreate INTO @ObjName,@QueryExec 95 | WHILE @@FETCH_STATUS = 0 BEGIN 96 | 97 | UPDATE msdb.dbo.SmartShrink 98 | SET StartCreate=GETDATE() 99 | WHERE ObjectName = @ObjName; 100 | 101 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText, QueryText) 102 | VALUES('#SmartShrink.#CreateIndex: before operation.',@QueryExec); 103 | EXECUTE sp_executesql @QueryExec; 104 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText, QueryText) 105 | VALUES('#SmartShrink.#CreateIndex: after operation.',@QueryExec); 106 | 107 | UPDATE msdb.dbo.SmartShrink 108 | SET EndCreate=GETDATE() 109 | WHERE ObjectName = @ObjName; 110 | 111 | FETCH NEXT FROM curCreate INTO @ObjName,@QueryExec 112 | END 113 | CLOSE curCreate; 114 | DEALLOCATE curCreate; 115 | END TRY 116 | BEGIN CATCH 117 | CLOSE curCreate; 118 | DEALLOCATE curCreate; 119 | THROW; 120 | END CATCH 121 | UPDATE msdb.dbo.SmartShrinkParams SET CreateIndex = 1 WHERE spid = @spid; 122 | END 123 | GO 124 | IF OBJECT_ID ('tempdb..#ShrinkFile','P') IS NOT NULL 125 | drop PROCEDURE #ShrinkFile; 126 | GO 127 | CREATE PROCEDURE #ShrinkFile(@spid INT,@TableSpace sysname = NULL,@ReserveFreeSpaceMB INT = 10) 128 | AS 129 | BEGIN 130 | DECLARE @QueryExec NVARCHAR(MAX); 131 | DECLARE curShrink CURSOR FOR SELECT N'USE '+QUOTENAME(DB_NAME())+N'; 132 | '+N'DBCC SHRINKFILE ('+CAST(a.FILEID AS NVARCHAR)+N','+CONVERT(NVARCHAR,(convert(int,round(fileproperty(a.name,'SpaceUsed')/128.000,3))+@ReserveFreeSpaceMB))+N')' 133 | FROM 134 | sys.sysfiles a 135 | INNER join sys.database_files df on df.file_id = a.fileid 136 | inner join sys.filegroups as fg on fg.data_space_id = df.data_space_id 137 | WHERE fg.name=@TableSpace OR @TableSpace IS NULL; 138 | BEGIN TRY 139 | OPEN curShrink; 140 | FETCH NEXT FROM curShrink INTO @QueryExec 141 | WHILE @@FETCH_STATUS = 0 BEGIN 142 | 143 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText, QueryText) 144 | VALUES('#SmartShrink.#ShrinkFile: before operation.',@QueryExec); 145 | EXECUTE sp_executesql @QueryExec; 146 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText, QueryText) 147 | VALUES('#SmartShrink.#ShrinkFile: after operation.',@QueryExec); 148 | 149 | FETCH NEXT FROM curShrink INTO @QueryExec 150 | END 151 | CLOSE curShrink; 152 | DEALLOCATE curShrink; 153 | END TRY 154 | BEGIN CATCH 155 | CLOSE curShrink; 156 | DEALLOCATE curShrink; 157 | THROW; 158 | END CATCH 159 | UPDATE msdb.dbo.SmartShrinkParams SET ShrinkFile = 1 WHERE spid = @spid; 160 | END 161 | GO 162 | IF OBJECT_ID ('tempdb..#DropIndex','P') IS NOT NULL 163 | drop PROCEDURE #DropIndex; 164 | GO 165 | CREATE PROCEDURE #DropIndex (@spid INT) 166 | AS 167 | BEGIN 168 | DECLARE @ObjName NVARCHAR(513), @QueryExec NVARCHAR(MAX); 169 | DECLARE curDrop CURSOR FOR SELECT ObjectName,QueryDrpIndex FROM msdb.dbo.SmartShrink WHERE spid = @spid AND EndDrop IS NULL; 170 | 171 | BEGIN TRY 172 | OPEN curDrop; 173 | FETCH NEXT FROM curDrop INTO @ObjName,@QueryExec 174 | WHILE @@FETCH_STATUS = 0 BEGIN 175 | 176 | UPDATE msdb.dbo.SmartShrink 177 | SET StartDrop=GETDATE() 178 | WHERE ObjectName = @ObjName; 179 | 180 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText, QueryText) 181 | VALUES('#SmartShrink.#DropIndex before operation.',@QueryExec); 182 | EXECUTE sp_executesql @QueryExec; 183 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText, QueryText) 184 | VALUES('#SmartShrink.#DropIndex after operation.',@QueryExec); 185 | 186 | UPDATE msdb.dbo.SmartShrink 187 | SET EndDrop=GETDATE() 188 | WHERE ObjectName = @ObjName; 189 | 190 | FETCH NEXT FROM curDrop INTO @ObjName,@QueryExec 191 | END 192 | CLOSE curDrop; 193 | DEALLOCATE curDrop; 194 | END TRY 195 | BEGIN CATCH 196 | CLOSE curDrop; 197 | DEALLOCATE curDrop; 198 | THROW; 199 | END catch 200 | UPDATE msdb.dbo.SmartShrinkParams SET DropIndex = 1 WHERE spid = @spid; 201 | END 202 | GO 203 | /*****************************************************************************************************************/ 204 | /* “”“ Ќј„јЋќ ¬’ќƒЌџ≈ ѕј–јћ≈“–џ */ 205 | DECLARE 206 | @ReserveFreeSpaceMB INT = 10, 207 | @TableSpace sysname = 'FG_2016'; 208 | 209 | /* —»—“≈ћЌџ≈ ѕј–јћ≈“–џ */ 210 | DECLARE 211 | @spid INT = @@SPID, 212 | @GetIndex BIT = 0, 213 | @CreateIndex BIT = 0, 214 | @ShrinkFile BIT = 0, 215 | @DropIndex BIT = 0; 216 | 217 | DECLARE @RunTable TABLE (spid INT,getIndex BIT,CreateIndex BIT,ShrinkFile BIT,DropIndex BIT); 218 | 219 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText) VALUES('#SmartShrink. start.'); 220 | 221 | BEGIN TRY 222 | -- загружаем прерванные сессии или создаем новую. 223 | INSERT INTO @RunTable( spid ,getIndex ,CreateIndex ,ShrinkFile ,DropIndex) 224 | SELECT TOP 1 spid,GetIndex,CreateIndex,ShrinkFile,DropIndex 225 | FROM msdb.dbo.SmartShrinkParams 226 | 227 | IF EXISTS (SELECT 1 FROM @RunTable) BEGIN 228 | SELECT 229 | @spid = spid, 230 | @GetIndex = getIndex, 231 | @CreateIndex = CreateIndex, 232 | @ShrinkFile = ShrinkFile, 233 | @DropIndex = DropIndex 234 | FROM @RunTable; 235 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText) VALUES('Find terminate session #'+CAST(@spid AS varchar)); 236 | END ELSE BEGIN 237 | INSERT INTO msdb.dbo.SmartShrinkParams( spid )VALUES(@spid); 238 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText) VALUES('Open new session #'+CAST(@spid AS varchar)); 239 | END 240 | 241 | -- получаем индексы 242 | IF @GetIndex = 0 243 | EXEC dbo.#GetIndex @spid = @spid, @TableSpace = @TableSpace 244 | 245 | -- построим индексы 246 | -- IF @CreateIndex = 0 247 | -- EXEC dbo.#CreateIndex @spid = @spid 248 | 249 | -- жмем файлы 250 | -- IF @ShrinkFile = 0 251 | -- EXEC dbo.#ShrinkFile @spid = @spid, @TableSpace = @TableSpace,@ReserveFreeSpaceMB = @ReserveFreeSpaceMB 252 | 253 | -- ”дал¤ем индексы 254 | -- IF @DropIndex = 0 255 | -- EXEC dbo.#DropIndex @spid = @spid 256 | 257 | -- “ипо все хорошо 258 | -- DELETE FROM msdb.dbo.SmartShrinkParams WHERE spid = @spid 259 | 260 | END TRY 261 | BEGIN CATCH 262 | DECLARE 263 | @ErrorNumber INT = ERROR_NUMBER(), 264 | @ErrorSeverity INT = ERROR_SEVERITY(), 265 | @ErrorState INT = ERROR_STATE(), 266 | @ErrorLine INT = ERROR_LINE(), 267 | @ErrorMessage VARCHAR(4000) = ERROR_MESSAGE(); 268 | 269 | IF XACT_STATE() = -1 270 | ROLLBACK TRAN 271 | IF (XACT_STATE()) = 1 272 | COMMIT TRANSACTION 273 | 274 | insert into msdb.dbo.SmartShrinkLog( MsgText, QueryText, SPID ) 275 | SELECT 'Error #'+CAST(@ErrorNumber AS VARCHAR)+' in line #'+CAST(@ErrorLine AS VARCHAR),@ErrorMessage,@spid; 276 | 277 | RAISERROR(@ErrorMessage,@ErrorSeverity,@ErrorState) WITH LOG; 278 | END CATCH; 279 | 280 | INSERT INTO msdb.dbo.SmartShrinkLog( MsgText) VALUES('#SmartShrink. finish.'); 281 | GO 282 | /*****************************************************************************************************************/ --------------------------------------------------------------------------------