<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:blogChannel="http://backend.userland.com/blogChannelModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
  <channel>
    <title>T-SQL.RU</title>
    <description>Всё об MS SQL Server 7.0 - 2019 на русском</description>
    <link>http://t-sql.ru/</link>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>BlogEngine.NET 2.7.0.0</generator>
    <language>ru-RU</language>
    <blogChannel:blogRoll>http://t-sql.ru/opml.axd</blogChannel:blogRoll>
    <dc:creator>Alexey Knyazev</dc:creator>
    <dc:title>T-SQL.RU</dc:title>
    <geo:lat>0.000000</geo:lat>
    <geo:long>0.000000</geo:long>
    <item>
      <title>Массовая замена текста в объектах SQL Server</title>
      <description>&lt;p&gt;&lt;img src="http://www.t-sql.ru/images/posh.png" alt="" align="left" /&gt;Если у вас возникнет потребность внести массовые изменения во все объекты БД (заменить одно значение на другое), то следующий скрипт сможет облегчить вам эту задачу. Кроме того, что он заменять указанный текст на новый, он ещё сохраняет на диск старую и новую версию файла, а это поможет вам в последствии легко заменить файлы в системе контроля версий, например, в TFS. &lt;br /&gt; Скрипт написан на PowerShell и в текущей реализации работает с процедурами, функциями, триггерами и представлениями, но может быть легко дополнен. Для выгрузки скриптов в файлы используются два параметра: &lt;strong&gt;$backupFolder&lt;/strong&gt; и &lt;strong&gt;$changeFolder&lt;/strong&gt;. Кроме того, если вам не нужно заменять объекты на сервере, а только выгрузить файлы для последующей замены, то достаточно поменять параметр &lt;strong&gt;$alter&lt;/strong&gt; с &lt;em&gt;$true&lt;/em&gt; на &lt;em&gt;$false&lt;/em&gt;.&lt;/p&gt;
&lt;pre class="brush: ps;"&gt;$ServerName=Read-Host "Укажите имя сервера БД"
# Определяем имя БД
$DatabaseName=Read-Host "Введите имя БД"
# Определяем текст для поиска
$OldText=Read-Host "Введите текст для поиска" 
# Определяем текст для замены
$NewText=Read-Host "Введите текст для замены" 

$backupFolder = "c:\temp\old\";  
$changeFolder = "c:\temp\new\";
$alter = $true;  

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null
$server=new-object("Microsoft.SqlServer.Management.Smo.Server") $ServerName
 
#Имя БД, с которой работаем
$db = $server.Databases[$DatabaseName]

 
# Создаём соединение
$SQLConnection = New-Object System.Data.SqlClient.SqlConnection("Data Source=$ServerName;Integrated Security=SSPI;Initial Catalog=$DatabaseName") 
 
# Создаем SQL команду, используя наш запрос и созданное соединение
$SQLCommand = New-Object System.Data.SqlClient.SqlCommand("
select object_schema_name(m.object_id) as sch
     , object_name(m.object_id) as obj
     , o.type   
     , o.type_desc
     , object_schema_name(o.parent_object_id) as parent_sch
     , object_name(o.parent_object_id) as parent_obj
    from sys.sql_modules m
        inner join sys.objects o
          on m.object_id = o.object_id
    where m.definition like '%$OldText%'
    order by 2
", $SQLConnection) 
 
# Открываем соединение
$SQLConnection.Open()
 
# Выполняем&amp;hellip;.
$SQLAdapter = New-Object System.Data.SqlClient.SqlDataAdapter($SQLCommand)
$DataSet = New-Object System.Data.DataSet;
$SQLAdapter.Fill($DataSet);
$DataTable=New-Object System.Data.DataTable
$DataTable=$DataSet.Tables[0]
 
$DataTable.DefaultView | Out-GridView

foreach ($Row in $DataTable.Rows)
{
   $type = $($Row[2])
   
   #StoredProcedures
   if ( $type -match "P" )
   {
    $proc = $db.StoredProcedures | where {$_.Schema -eq $($Row[0]) -and $_.Name -eq $($Row[1])}
    $proc.Script() | Out-File ($backupFolder + "StoredProcedures\" + [string]$proc.name + ".sql");
    $proc.Script() -replace($OldText, $NewText) | Out-File ($changeFolder + "StoredProcedures\" + [string]$proc.name + ".sql");
        if($alter)
        {
        $proc.TextBody = $proc.TextBody -replace($OldText, $NewText);
        $proc.Alter();
        Write-Host "Altered " $proc.Name;
        }    
   }
   
   #Views
   if ( $type -match "V" )
   {
    $view = $db.Views | where {$_.Schema -eq $($Row[0]) -and $_.Name -eq $($Row[1])}
    $view.Script() | Out-File ($backupFolder + "Views\" + [string]$view.name + ".sql");
    $view.Script() -replace($OldText, $NewText) | Out-File ($changeFolder + "Views\" + [string]$view.name + ".sql");
        if($alter)
        {
        $view.TextBody = $view.TextBody -replace($OldText, $NewText);
        $view.Alter();
        Write-Host "Altered " $view.Name;
        }    
   }
   
   #Triggers
   if ( $type -match "TR" )
   {
    $table = $db.Tables | where {$_.Schema -eq $($Row[4]) -and $_.Name -eq $($Row[5])}
    $trigger = $table.Triggers | where {$_.Name -eq $($Row[1])}
    $trigger.Script() | Out-File ($backupFolder + "Triggers\" + [string]$trigger.name + ".sql");
    $trigger.Script() -replace($OldText, $NewText) | Out-File ($changeFolder + "Triggers\" + [string]$trigger.name + ".sql");
        if($alter)
        {
        $trigger.TextBody = $trigger.TextBody -replace($OldText, $NewText);
        $trigger.Alter();
        Write-Host "Altered " $trigger.Name;
        }    
   }
   
   #UserDefinedFunctions (SQL_SCALAR_FUNCTION, SQL_INLINE_TABLE_VALUED_FUNCTION, SQL_TABLE_VALUED_FUNCTION)
   if ( ( $type -match "FN" ) -or ( $type -match "IF" ) -or ( $type -match "TF" ) )
   {
    $func = $db.UserDefinedFunctions | where {$_.Schema -eq $($Row[0]) -and $_.Name -eq $($Row[1])}
    $func.Script() | Out-File ($backupFolder + "UserDefinedFunctions\" + [string]$func.name + ".sql");
    $func.Script() -replace($OldText, $NewText) | Out-File ($changeFolder + "UserDefinedFunctions\" + [string]$func.name + ".sql");
        if($alter)
        {
        $func.TextBody = $func.TextBody -replace($OldText, $NewText);
        $func.Alter();
        Write-Host "Altered " $func.Name;
        }    
   }
     
}

# Закрываем соединение
$SQLConnection.Close()&lt;/pre&gt;</description>
      <link>http://t-sql.ru/post/modify.aspx</link>
      <author>a.knyazev@t-sql.ru</author>
      <comments>http://t-sql.ru/post/modify.aspx#comment</comments>
      <guid>http://t-sql.ru/post.aspx?id=ed21e081-da69-4c2d-8f55-8b9f437c4c77</guid>
      <pubDate>Tue, 27 Sep 2016 23:57:00 +0800</pubDate>
      <category>PowerShell</category>
      <category>SQL Server</category>
      <dc:publisher>Alexey Knyazev</dc:publisher>
      <pingback:server>http://t-sql.ru/pingback.axd</pingback:server>
      <pingback:target>http://t-sql.ru/post.aspx?id=ed21e081-da69-4c2d-8f55-8b9f437c4c77</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://t-sql.ru/trackback.axd?id=ed21e081-da69-4c2d-8f55-8b9f437c4c77</trackback:ping>
      <wfw:comment>http://t-sql.ru/post/modify.aspx#comment</wfw:comment>
      <wfw:commentRss>http://t-sql.ru/syndication.axd?post=ed21e081-da69-4c2d-8f55-8b9f437c4c77</wfw:commentRss>
    </item>
    <item>
      <title>Минимальное протоколирование (MIN_LOGGED) и полная (FULL) модель восстановления</title>
      <description>&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2016%2f04%2fmin_log00.PNG" alt="" /&gt;&lt;br&gt;SQL Server позволяет повысить производительность ряда операций за счёт минимального протоколирование изменений в журнал транзакций. &lt;br /&gt; &lt;em&gt;Минимальное протоколирование &amp;mdash; это протоколирование только информации, необходимой для восстановления транзакции без поддержки восстановления на момент времени.&lt;/em&gt; &lt;br /&gt; Список таких операций впечатляет (&lt;a href="https://msdn.microsoft.com/ru-ru/library/ms190925.aspx"&gt;https://msdn.microsoft.com/ru-ru/library/ms190925.aspx&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Операции массового импорта (bcp, BULK INSERT и INSERT... SELECT)&lt;/li&gt;
&lt;li&gt;Операции SELECT INTO&lt;/li&gt;
&lt;li&gt;Инструкции WRITETEXT и UPDATETEXT при вставке или добавлении новых данных в столбцы с типом данных text, ntext и image&lt;/li&gt;
&lt;li&gt;Частичные обновления типов данных с большими значениями с помощью предложений. WRITE инструкции UPDATE при вставке или добавлении новых данных&lt;/li&gt;
&lt;li&gt;Операции с индексами (CREATE INDEX [включая индексированные представления], ALTER INDEX REBUILD или DBCC DBREINDEX, DROP INDEX), тесты над индексами я проводил ранее - &lt;a href="http://t-sql.ru/post/index_minimally_logged.aspx"&gt;http://t-sql.ru/post/index_minimally_logged.aspx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;За счёт минимального протоколирования можно в разы сократить время выполнения привычных запросов, но это возможно, только если у вас используется модель восстановления &amp;ndash; простая (&lt;strong&gt;SIMPLE&lt;/strong&gt;) или модель восстановления с неполным протоколированием (&lt;strong&gt;BULK LOGGED&lt;/strong&gt;). &lt;br /&gt; Как же быть, если мы используем полную модель восстановления (&lt;strong&gt;FULL&lt;/strong&gt;)? В &lt;strong&gt;BOL&lt;/strong&gt; по этому поводу написано: &lt;br /&gt; &lt;em&gt;В модели полного восстановления все массовые операции полностью протоколируются. Однако для набора массовых операций можно использовать минимальное протоколирование, временно переключив базу данных на модель восстановления с неполным протоколированием во время массовых операций. Минимальное протоколирование более эффективно, чем полное, и снижает вероятность того, что во время массовой операции большого объема будет заполнено все доступное пространство журнала транзакций. Однако, если при включенном минимальном протоколировании база данных будет повреждена или потеряна, ее нельзя будет восстановить до точки сбоя.&lt;/em&gt;&lt;br /&gt; Но всё ли так однозначно? Давайте проведём небольшое тестирование одной из операций с минимальным протоколированием (операции массового импорта) в полной модели восстановления.&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;use master;
go

--Удалим БД, если она уже существует
if db_id( 'MIN_LOGGED' ) is not null
begin
  alter database MIN_LOGGED set restricted_user with rollback immediate;
  drop database MIN_LOGGED;
end

--Создадим БД для тестов
create database MIN_LOGGED;
go
--Переключим модель в режим полного протоколирования
alter database MIN_LOGGED set recovery full;
go
--Переключение на модель полного восстановления или модель восстановления с неполным протоколированием 
--вступает в силу только после создания первой резервной копии данных
backup database MIN_LOGGED to disk = 'c:\temp\MIN_LOGGED_01.bak';
go

use MIN_LOGGED;
go

--Создадим 2 таблицы для тестов
create table dbo.test_table_01 (id int identity, val varchar(255));
go
create table dbo.test_table_02 (id int identity, val varchar(255));
go
set statistics time on;
go
--Вставка с хинтом TABLOCK 
--(позволяет использовать минимальное протоколирование для массовой загрузки)
--https://msdn.microsoft.com/ru-ru/library/ms190422.aspx
insert into dbo.test_table_01 with (tablock)
select replicate('A', 255) from sys.all_objects t1, sys.all_objects t2;
go
insert into dbo.test_table_02
select replicate('A', 255) from sys.all_objects t1, sys.all_objects t2;
go
set statistics time off;
go&lt;/pre&gt;
&lt;pre class="brush: sql;"&gt;/*
SQL Server Execution Times:
  CPU time = 5445 ms,  elapsed time = 211902 ms.
SQL Server Execution Times:
  CPU time = 16333 ms,  elapsed time = 280117 ms.
*/&lt;/pre&gt;
Разница во времени выполнения запросов существенна &lt;b&gt;211&lt;/b&gt; vs &lt;b&gt;280&lt;/b&gt; секунд (или 25%). Обратимся к журналу транзакций:
&lt;pre class="brush: sql;"&gt;
--Посмотрим сколько строк у нас записалось в журнал транзакций
select count(*) cnt 
  from fn_dblog( default, default )
  where AllocUnitName like 'dbo.test_table_01%';
go

select count(*) cnt 
  from fn_dblog( default, default )
  where AllocUnitName like 'dbo.test_table_02%';
go
&lt;/pre&gt;
&lt;img src="http://t-sql.ru/image.axd?picture=%2f2016%2f04%2fmin_log01.PNG" /&gt;
&lt;br&gt;
Кроме того, в ряде случаев страница &lt;b&gt;BCM - Bulk Change Map&lt;/b&gt; (Схема массовых изменений), она отслеживает экстенты, измененные операциями с неполным протоколированием, показывает нам что операция выполнялась с минимальным протоколированием.
&lt;br&gt;&lt;br&gt;
Всё это наталкивает на мысль, что, несмотря на всю документацию, при полной модели восстановления мы получили неполное протоколирование, а это, как мы помним, чревато потерей данных, т.к. мы не сможем восстановить БД на определённый момент времени.&lt;br&gt;
Давайте попробуем удалить часть данных в транзакции и восстановиться на время начала этой транзакции.
&lt;pre class="brush: sql;"&gt;

--Запомним, сколько записей в dbo.test_table_01
exec sp_spaceused 'dbo.test_table_01'; --4 647 336                          
go 
begin transaction flag with mark 'flag';
delete top (1000) from dbo.test_table_01;
commit transaction
go
--Убедимся, что удаление произошло
exec sp_spaceused 'dbo.test_table_01'; --4 646 336                                       
go 
--Очистим таблицу
truncate table dbo.test_table_01;
go
--Сделаем резервную копию журнала транзакций
backup log MIN_LOGGED to disk = 'c:\temp\MIN_LOGGED_ldf_01.bak';
go

--Восстановим БД на момент начала транзакции "flag"
use master;
go
restore database MIN_LOGGED from disk = 'c:\temp\MIN_LOGGED_01.bak' with norecovery, replace;
go
restore database MIN_LOGGED from disk = 'c:\temp\MIN_LOGGED_ldf_01.bak' with stopatmark = 'flag', recovery;
go

use MIN_LOGGED;
go
exec sp_spaceused 'dbo.test_table_01'; --4 646 336                                       
go 
&lt;/pre&gt;
Вуаля!!!, мы смогли восстановиться на нужную нам «точку». Но почему же у нас операция была помечена, как операция с минимальным протоколированием и почему операция выполнилась быстрее?
&lt;br&gt;
&lt;b&gt;Во-первых&lt;/b&gt;, страница Bulk Change Map актуальна только для модели восстановления с неполным протоколированием (BULK LOGGED). 
&lt;br&gt;
&lt;b&gt;Во-вторых&lt;/b&gt;, ряд операций минимально протоколируется и при полной модели восстановления, например, TRUNCATE (в журнал транзакций записывает только данные об освобождении страниц).
&lt;br&gt; 
&lt;b&gt;В-третьих&lt;/b&gt;, при анализе журнала транзакций, необходимо смотреть не только кол-во операций, которые попали в лог, но и их размер [Log Record Length], тогда разница будет уже не такая существенная.&lt;br&gt;&lt;br&gt;
Основное отличие в том, что SQL Server для операций массовой вставки выделяет сразу целые страницы и экстенты, а не по строкам, тем самым количество записей существенно меньше, но их размер больше.

&lt;img src="http://t-sql.ru/image.axd?picture=%2f2016%2f04%2fmin_log02.PNG" /&gt;
&lt;br&gt;
Но основное преимущество от минимального протоколирования мы сможем получить только при режиме восстановления BULK LOGGED, либо SIMPLE. И если проделать все операции, описанные выше, уже при одной из этих моделей, то мы получим следующие цифры (что уже на порядок лучше):
&lt;pre class="brush: sql;"&gt;
SQL Server Execution Times:
  CPU time = 15476 ms,  elapsed time = 82727 ms.

SQL Server Execution Times:
  CPU time = 16801 ms,  elapsed time = 202738 ms.
&lt;/pre&gt;
&lt;img src="http://t-sql.ru/image.axd?picture=%2f2016%2f04%2fmin_log03.PNG" /&gt;
&lt;br&gt;&lt;br&gt;
А при попытке восстановить БД на определённый момент времени мы получим ошибку:
&lt;br&gt;&lt;br&gt;
&lt;img src="http://t-sql.ru/image.axd?picture=%2f2016%2f04%2fmin_log04.PNG" /&gt;
&lt;br&gt;&lt;br&gt;
Помните об этой особенности, когда пишите свой код. Даже при полной модели восстановления можно получить более эффективные запросы.
&lt;br&gt;
&lt;br&gt;Ссылка по теме: &lt;a href="http://www.enabledbusinesssolutions.com/blog/?p=1222"&gt;http://www.enabledbusinesssolutions.com/blog/?p=1222&lt;/a&gt;
</description>
      <link>http://t-sql.ru/post/min_logged_with_full_recovery.aspx</link>
      <author>a.knyazev@t-sql.ru</author>
      <comments>http://t-sql.ru/post/min_logged_with_full_recovery.aspx#comment</comments>
      <guid>http://t-sql.ru/post.aspx?id=4ad7d0e3-5bda-42a9-88c6-f07b42593b86</guid>
      <pubDate>Sat, 02 Apr 2016 19:14:00 +0800</pubDate>
      <category>SQL Server</category>
      <dc:publisher>Alexey Knyazev</dc:publisher>
      <pingback:server>http://t-sql.ru/pingback.axd</pingback:server>
      <pingback:target>http://t-sql.ru/post.aspx?id=4ad7d0e3-5bda-42a9-88c6-f07b42593b86</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://t-sql.ru/trackback.axd?id=4ad7d0e3-5bda-42a9-88c6-f07b42593b86</trackback:ping>
      <wfw:comment>http://t-sql.ru/post/min_logged_with_full_recovery.aspx#comment</wfw:comment>
      <wfw:commentRss>http://t-sql.ru/syndication.axd?post=4ad7d0e3-5bda-42a9-88c6-f07b42593b86</wfw:commentRss>
    </item>
    <item>
      <title>24 Hours of PASS, 2016</title>
      <description>&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2016%2f04%2fPASS_24HOP_2016_Banner.jpg" alt="" /&gt; &lt;br /&gt;&lt;br /&gt; 16 - 17 марта 2016 года прошла 5-ая конференция &lt;a href="&amp;quot;http://www.sqlpass.org/24hours/2016/russian/%D0%93%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F.aspx"&gt;24 Hours of PASS&lt;/a&gt; &lt;br /&gt; Записи докладов: &lt;a href="https://www.youtube.com/user/russianvc"&gt;https://www.youtube.com/user/russianvc&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt; Мой доклад &lt;strong&gt;SQL Server 2016. Temporal Tables&lt;/strong&gt;: &lt;br /&gt;&lt;br /&gt; Temporal Tables - это один из новых функционалов, который появится в SQL Server 2016. &lt;br /&gt; В докладе мы подробно рассмотрим эту технологию, поговорим о преимуществах от её использования на примере реальных задач. Сравним с другими способами отслеживания изменений, такими, как логирование с помощью DML-триггеров, Change Tracking (CT) и Change Data Capture (CDC). &lt;br /&gt; &lt;br /&gt;[youtube:-6tr7Mo5C3c] &lt;br /&gt; Презентация и архив с примерами.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://t-sql.ru/FILES%2f2016%2f06%2fTemporal_Tables.pptx.axdx"&gt;Temporal_Tables.pptx (2,90 mb)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://t-sql.ru/FILES%2f2016%2f06%2fDemo.zip.axdx"&gt;Demo.zip (6,44 kb)&lt;/a&gt;&lt;/p&gt;</description>
      <link>http://t-sql.ru/post/Temporal_Tables.aspx</link>
      <author>a.knyazev@t-sql.ru</author>
      <comments>http://t-sql.ru/post/Temporal_Tables.aspx#comment</comments>
      <guid>http://t-sql.ru/post.aspx?id=fdcdf3fd-908c-4110-959b-a6b7ccb8075e</guid>
      <pubDate>Wed, 30 Mar 2016 19:55:00 +0800</pubDate>
      <category>SQL Server</category>
      <dc:publisher>Alexey Knyazev</dc:publisher>
      <pingback:server>http://t-sql.ru/pingback.axd</pingback:server>
      <pingback:target>http://t-sql.ru/post.aspx?id=fdcdf3fd-908c-4110-959b-a6b7ccb8075e</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://t-sql.ru/trackback.axd?id=fdcdf3fd-908c-4110-959b-a6b7ccb8075e</trackback:ping>
      <wfw:comment>http://t-sql.ru/post/Temporal_Tables.aspx#comment</wfw:comment>
      <wfw:commentRss>http://t-sql.ru/syndication.axd?post=fdcdf3fd-908c-4110-959b-a6b7ccb8075e</wfw:commentRss>
    </item>
    <item>
      <title>Error 5161: An unexpected file id was encountered. File id %d was expected but %d was read from</title>
      <description>&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2016%2f04%2fico-14485%2c256.png" alt="" width="121" height="121" align="left" /&gt;Ошибка 5161 - &lt;em&gt;&lt;span style="color: #ff0000;"&gt;An unexpected file id was encountered. File id %d was expected but %d was read from "%.*ls". Verify that files are mapped correctly in sys.master_files. ALTER DATABASE can be used to correct the mappings&lt;/span&gt;.&lt;/em&gt; &lt;br /&gt;может возникнуть, когда вы пытаетесь подменить файлы БД.&lt;/p&gt;
&lt;p&gt;Сценарий: у вас есть в наличии физические файлы базы данных (например, перенесены с другого сервера после краха) и вам нужно эти файлы подключить к серверу. Основной порядок действий в этом случаи может быть следующий:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Создать новую БД с аналогичной структурой&lt;/li&gt;
&lt;li&gt;С помощью операции ALTER DATABASE ... MODIFY FILE указать расположение файлов, которые нам нужно "подцепить"&lt;/li&gt;
&lt;li&gt;Перезапуск SQL Server&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;После этого, вместо того, чтобы получить доступ к данным, ваша БД переходит в статус &lt;strong&gt;Recovery Pending&lt;/strong&gt;. &lt;br /&gt;Если посмотреть журнал ошибок SQL Server, то там могут присутствовать ошибки: &lt;img src="http://t-sql.ru/image.axd?picture=%2f2016%2f04%2ferror_01.PNG" alt="" /&gt; &lt;br /&gt;&lt;br&gt; Причина этой ошибки в том, что файлы вашей исходной БД имели другие идентификаторы, например: &lt;br&gt;&lt;br&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2016%2f04%2ferror_02.PNG" alt="" /&gt; &lt;br /&gt;&lt;br&gt; А когда вы создаёте пустую БД, то файлы идут по порядку:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;CREATE DATABASE [MyDB]
 ON  PRIMARY 
( NAME = N'db', FILENAME = N'c:\temp\db\db.MDF'  ),
( NAME = N'FG_01', FILENAME = N'c:\temp\db\01.ndf'  ),
( NAME = N'FG_02', FILENAME = N'c:\temp\db\02.ndf'  ),
( NAME = N'FG_03', FILENAME = N'c:\temp\db\03.ndf'  ),
( NAME = N'FG_04', FILENAME = N'c:\temp\db\04.ndf'  ),
( NAME = N'FG_05', FILENAME = N'c:\temp\db\05.ndf'  ),
( NAME = N'FG_06', FILENAME = N'c:\temp\db\06.ndf'  )
 LOG ON
( NAME = N'db_log', FILENAME = N'c:\temp\db\db_Log.LDF' )
go&lt;/pre&gt;
&lt;img src="http://t-sql.ru/image.axd?picture=%2f2016%2f04%2ferror_03.PNG" /&gt;
&lt;br&gt;&lt;br&gt;Если попытаться "подсунуть" файлы нужной БД на место текущих, то мы получим ошибку, озвученную выше. Для того, чтобы её избежать необходимо убедиться, что порядок файлов в sys.master_files соответствует, тому, что указан внутри системной таблицы sys.sysprufiles (object_id = 24), которая хранится в mdf-файле.&lt;br&gt;
Самый простой сценарий для подключения файлов в такой БД:
&lt;pre class="brush: sql;"&gt;
--Создание пустой БД
create DATABASE [MyDB]
 ON  PRIMARY 
( NAME = N'db', FILENAME = N'c:\temp\db\db.MDF'  ),
--2 файла для подмены
( NAME = N'FG_xx1', FILENAME = N'c:\temp\db\xx1.ndf'  ),
( NAME = N'FG_xx2', FILENAME = N'c:\temp\db\xx2.ndf'  ),
---------------------
( NAME = N'FG_01', FILENAME = N'c:\temp\db\01.ndf'  ),
( NAME = N'FG_02', FILENAME = N'c:\temp\db\02.ndf'  ),
( NAME = N'FG_03', FILENAME = N'c:\temp\db\03.ndf'  ),
( NAME = N'FG_04', FILENAME = N'c:\temp\db\04.ndf'  ),
( NAME = N'FG_05', FILENAME = N'c:\temp\db\05.ndf'  ),
( NAME = N'FG_06', FILENAME = N'c:\temp\db\06.ndf'  )
 LOG ON
( NAME = N'db_log', FILENAME = N'c:\temp\db\db_Log.LDF' );
go

--теперь можно эти файлы удалить
alter database [MyDB] remove file FG_xx1;
go
alter database [MyDB] remove file FG_xx2;
go

--Указываем новое расположение файлов (файлы, которые необходимо подключить)

ALTER DATABASE MyDB
MODIFY FILE (NAME = db, FILENAME = N'c:\temp\db\new\db.MDF');
go
ALTER DATABASE MyDB
MODIFY FILE (NAME = db_log, FILENAME = N'c:\temp\db\new\db_log.LDF');
GO
ALTER DATABASE MyDB
MODIFY FILE (NAME = FG_01, FILENAME = N'c:\temp\db\new\01.ndf');
GO
ALTER DATABASE MyDB
MODIFY FILE (NAME = FG_02, FILENAME = N'c:\temp\db\new\02.ndf');
GO
ALTER DATABASE MyDB
MODIFY FILE (NAME = FG_03, FILENAME = N'c:\temp\db\new\03.ndf');
go
ALTER DATABASE MyDB
MODIFY FILE (NAME = FG_04, FILENAME = N'c:\temp\db\new\04.ndf');
go
ALTER DATABASE MyDB
MODIFY FILE (NAME = FG_05, FILENAME = N'c:\temp\db\new\05.ndf');
go
ALTER DATABASE MyDB
MODIFY FILE (NAME = FG_06, FILENAME = N'c:\temp\db\new\06.ndf');
go
&lt;/pre&gt;</description>
      <link>http://t-sql.ru/post/error_5161.aspx</link>
      <author>a.knyazev@t-sql.ru</author>
      <comments>http://t-sql.ru/post/error_5161.aspx#comment</comments>
      <guid>http://t-sql.ru/post.aspx?id=f7b3339f-789a-4e8d-891e-a3b1e640a8ed</guid>
      <pubDate>Mon, 08 Feb 2016 20:38:00 +0800</pubDate>
      <category>SQL Server</category>
      <dc:publisher>Alexey Knyazev</dc:publisher>
      <pingback:server>http://t-sql.ru/pingback.axd</pingback:server>
      <pingback:target>http://t-sql.ru/post.aspx?id=f7b3339f-789a-4e8d-891e-a3b1e640a8ed</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://t-sql.ru/trackback.axd?id=f7b3339f-789a-4e8d-891e-a3b1e640a8ed</trackback:ping>
      <wfw:comment>http://t-sql.ru/post/error_5161.aspx#comment</wfw:comment>
      <wfw:commentRss>http://t-sql.ru/syndication.axd?post=f7b3339f-789a-4e8d-891e-a3b1e640a8ed</wfw:commentRss>
    </item>
    <item>
      <title>Compress и Decompress</title>
      <description>&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fMicrosoft_SQL_Server_2014_logo.jpg" alt="" align="left" /&gt;Рассмотрим ещё одну новую возможность, которая появилась в SQL Server 2016 CTP 3.1. Это встроенная поддержка сжатия GZIP: &lt;a href="https://msdn.microsoft.com/ru-ru/library/mt622775.aspx"&gt;COMPRESS&lt;/a&gt; и &lt;a href="https://msdn.microsoft.com/ru-ru/library/mt622776.aspx"&gt;DECOMPRESS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;В данной статье я попробую оценить эффективность использования встроенного сжатия. Посмотрим, какой объём занимают сжатые данные и оценим время, которое SQL Server тратит на сжатие и извлечение данных.&lt;/p&gt;
&lt;p&gt;Для начала убедитесь, что вы используете&lt;a href="https://www.microsoft.com/en-us/evalcenter/evaluate-sql-server-2016"&gt; SQL Server 2016 CTP 3.1 &lt;/a&gt;и выше. Я использую &lt;em&gt;Microsoft SQL Server 2016 (CTP3.2) - 13.0.900.73 (X64)&amp;nbsp;&amp;nbsp; Dec 10 2015 18:49:31&amp;nbsp;&amp;nbsp; Copyright (c) Microsoft Corporation&amp;nbsp; Enterprise Evaluation Edition (64-bit) on Windows 10 Enterprise 6.3 &amp;lt;X64&amp;gt; (Build 10586: ).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Создадим&amp;nbsp;2 таблицы:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;--Простая таблица с текстовым полем
create table SimpleTable ( val varchar(max) );
go

--Таблица с GZIP
create table SimpleTableGZIP ( val varbinary(max) );
go
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;Наполним данными:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;--SIMPLE
insert into SimpleTable
select replicate('A', 10000);
go 1000

--GZIP
insert into SimpleTableGZIP
select compress ( replicate('A', 10000) );
go 1000&lt;/pre&gt;
&lt;p&gt;Теперь сравним их объём:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;select object_name( object_id ) table_name
     , reserved_page_count
     , ( reserved_page_count ) * 8. sizeKb
     , row_count
  from sys.dm_db_partition_stats
  where object_id in ( object_id( 'SimpleTable' )
                     , object_id( 'SimpleTableGZIP' )
                     );&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f12%2fgzip1.PNG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;А теперь небольшой тест на скорость вставки:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;set statistics time on;
go
insert into SimpleTable
select t1.name + t2.name from sys.all_objects t1, sys.all_objects t2;
go
insert into SimpleTableGZIP
select compress ( t1.name + t2.name ) from sys.all_objects t1, sys.all_objects t2;
go
set statistics time off;
go
&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f12%2fgzip2.PNG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;И тест на извлечение данных:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;set statistics time on;
go
select * into #t1 
  from SimpleTable
go
select decompress(val) val into #t2
  from SimpleTableGZIP;
go
set statistics time off;
go&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f12%2fgzip3.PNG" alt="" /&gt;&lt;/p&gt;</description>
      <link>http://t-sql.ru/post/gzip.aspx</link>
      <author>a.knyazev@t-sql.ru</author>
      <comments>http://t-sql.ru/post/gzip.aspx#comment</comments>
      <guid>http://t-sql.ru/post.aspx?id=79c83e08-3ebb-4f30-bb1b-9eaa52ba15d1</guid>
      <pubDate>Mon, 28 Dec 2015 02:16:00 +0800</pubDate>
      <category>SQL Server</category>
      <dc:publisher>Alexey Knyazev</dc:publisher>
      <pingback:server>http://t-sql.ru/pingback.axd</pingback:server>
      <pingback:target>http://t-sql.ru/post.aspx?id=79c83e08-3ebb-4f30-bb1b-9eaa52ba15d1</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://t-sql.ru/trackback.axd?id=79c83e08-3ebb-4f30-bb1b-9eaa52ba15d1</trackback:ping>
      <wfw:comment>http://t-sql.ru/post/gzip.aspx#comment</wfw:comment>
      <wfw:commentRss>http://t-sql.ru/syndication.axd?post=79c83e08-3ebb-4f30-bb1b-9eaa52ba15d1</wfw:commentRss>
    </item>
    <item>
      <title>DROP IF EXISTS</title>
      <description>&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fMicrosoft_SQL_Server_2014_logo.jpg" alt="" align="left" /&gt;&lt;/p&gt;
&lt;p&gt;С выходом &lt;a href="http://blogs.technet.com/b/dataplatforminsider/archive/2015/10/28/sql-server-2016-community-technology-preview-3-0-is-available.aspx"&gt;SQL Server 2016 CTP3&lt;/a&gt; нас ожидает приятное дополнение в синтаксисе.&lt;/p&gt;
&lt;p&gt;Изменения касаются DDL операций &lt;a href="https://msdn.microsoft.com/en-us/library/ms173790.aspx"&gt;DROP&lt;/a&gt; и &lt;a href="https://msdn.microsoft.com/en-us/library/ms190273.aspx"&gt;ALTER TABLE&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Теперь любую операцию по удалению объекта (таблицы, процедуры, функции, триггеры, индексы и т.д.),&amp;nbsp;или столбца таблицы можно выполнить проще с помощью инструкции &lt;strong&gt;DROP IF EXISTS&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Для проверки существования объекта, перед его созданием использовался скрипт на подобии того, что ниже:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;--1)
if object_id ( N'dbo.TestTable', N'U' ) is not null
drop table dbo.TestTable;
go

create table dbo.TestTable ( id int identity );
go

--2)
if exists ( select * from sys.tables t
              inner join sys.schemas s
                on t.schema_id = s.schema_id
              where t.name = N'TestTable' 
                and s.name = N'dbo'
          )
drop table dbo.TestTable;
go

create table dbo.TestTable ( id int identity );
go
&lt;/pre&gt;
&lt;p&gt;Теперь есть ещё один способ (только начиная с &lt;strong&gt;CTP3&lt;/strong&gt; SQL Server 2016):&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;--3)
drop table if exists dbo.TestTable;
go

create table dbo.TestTable ( id int identity );
go
&lt;/pre&gt;
&lt;p&gt;Синтаксис поддерживается для следующих объектов:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fdie.PNG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Кроме объектов, подобную конструкцию можно использовать и при удалении столбцов и ограничений:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fdie2.PNG" alt="" /&gt;&lt;/p&gt;</description>
      <link>http://t-sql.ru/post/drop_if_exists.aspx</link>
      <author>a.knyazev@t-sql.ru</author>
      <comments>http://t-sql.ru/post/drop_if_exists.aspx#comment</comments>
      <guid>http://t-sql.ru/post.aspx?id=f133f2ef-1629-488a-acaf-854a275a5a2c</guid>
      <pubDate>Thu, 05 Nov 2015 02:52:00 +0800</pubDate>
      <category>SQL Server</category>
      <dc:publisher>Alexey Knyazev</dc:publisher>
      <pingback:server>http://t-sql.ru/pingback.axd</pingback:server>
      <pingback:target>http://t-sql.ru/post.aspx?id=f133f2ef-1629-488a-acaf-854a275a5a2c</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://t-sql.ru/trackback.axd?id=f133f2ef-1629-488a-acaf-854a275a5a2c</trackback:ping>
      <wfw:comment>http://t-sql.ru/post/drop_if_exists.aspx#comment</wfw:comment>
      <wfw:commentRss>http://t-sql.ru/syndication.axd?post=f133f2ef-1629-488a-acaf-854a275a5a2c</wfw:commentRss>
    </item>
    <item>
      <title>Как на t-sql узнать запущена ли служба SQL Server, а если запущена, то под кем? </title>
      <description>&lt;p&gt;&lt;img style="width: 148px; height: 135px; float: right;" src="http://t-sql.ru/image.axd?picture=%2f2015%2f09%2fwindows_services_gear.png" alt="" width="255" height="256" align="left" /&gt; Вопросы, которые периодически задают многие:&lt;/p&gt;
&lt;p&gt;"Как узнать статус служб SQL сервер?"&lt;/p&gt;
&lt;p&gt;"Как узнать под кем стартует сервис?"&lt;/p&gt;
&lt;p&gt;"Как всё это сделать с помощью запроса T-SQL?"&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Параметры служб&amp;nbsp;можно легко получить через стандартную оснаску Windows "Службы (Services)" - &lt;strong&gt;services.msc&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style="width: 636px; height: 204px;" src="http://t-sql.ru/image.axd?picture=%2f2015%2f09%2f1.png" alt="" width="837" height="290" /&gt;&lt;/p&gt;
&lt;p&gt;Либо через стандартную утилиту SQL Server Configuration Manager - &lt;strong&gt;SQLServerManagerXX.msc&lt;/strong&gt;, где XX - номер версии SQL Server.&lt;/p&gt;
&lt;p&gt;&lt;img style="width: 598px; height: 138px;" src="http://t-sql.ru/image.axd?picture=%2f2015%2f09%2f2.PNG" alt="" width="868" height="182" /&gt;&lt;/p&gt;
&lt;p&gt;Но получить эту информацию на удалённом сервере можно и через запрос на T-SQL. Вот несколько способов:&lt;/p&gt;
&lt;p&gt;1) Недокументированная процедура &lt;strong&gt;master..xp_servicecontrol&lt;/strong&gt; у которой 2 входных параметра - команда (&lt;em&gt;start/stop/pause/continue/querystate&lt;/em&gt;) и имя службы. Эта процедура позволяет перезапускать службы и просматривать текущий статус.&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;exec master.. xp_servicecontrol @Action = 'querystate', @ServiceName = N'MSSQLSERVER';&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f09%2f3.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;2) Используем недокументированную процедуру &lt;strong&gt;master..xp_regread&lt;/strong&gt;, которая позволяет считывать настройки из реестра.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;img style="width: 635px; height: 217px;" src="http://t-sql.ru/image.axd?picture=%2f2015%2f09%2f4.PNG" alt="" width="923" height="248" /&gt;&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;declare @ServiceName sysname;
exec master..xp_regread
      'HKEY_LOCAL_MACHINE'
    , 'SYSTEM\CurrentControlSet\services\MSSQLSERVER'
    , 'ObjectName' 
    , @ServiceName OUTPUT;
select @ServiceName as 'Log On As';
&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f09%2f5.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;3) Через &lt;strong&gt;WMI&lt;/strong&gt; (Windows Management Instrumentation)&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;exec master..xp_cmdshell 'wmic service where "Name like ''%sql%''" get Caption, StartName, Started';
&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f09%2f6.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;4) Через утилиту командной строки &lt;strong&gt;SC.exe&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;exec master..xp_cmdshell 'SC query MSSQLSERVER';
&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f09%2f7.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;5) С помощью запроса на PoSh (&lt;strong&gt;PowerShell&lt;/strong&gt;):&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;exec master..xp_cmdshell '""C:\WINDOWS\system32\windowspowershell\v1.0\powershell" "get-service MSSQLSERVER | Format-List *""';&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f09%2f8.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;6) В SQL Server 2008R2 +SP1 появилось новое Динамическое административное представление &lt;strong&gt;&lt;a href="https://msdn.microsoft.com/ru-ru/library/hh204542(v=sql.105).aspx"&gt;sys.dm_server_services&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;select servicename, service_account, status_desc from sys.dm_server_services;
&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f09%2f9.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;7) CLR-сборка&lt;/p&gt;</description>
      <link>http://t-sql.ru/post/xp_servicecontrol.aspx</link>
      <author>a.knyazev@t-sql.ru</author>
      <comments>http://t-sql.ru/post/xp_servicecontrol.aspx#comment</comments>
      <guid>http://t-sql.ru/post.aspx?id=02faaa09-e03b-45f8-9dd8-6bc219c70beb</guid>
      <pubDate>Tue, 29 Sep 2015 00:00:00 +0800</pubDate>
      <category>PowerShell</category>
      <category>SQL Server</category>
      <dc:publisher>Alexey Knyazev</dc:publisher>
      <pingback:server>http://t-sql.ru/pingback.axd</pingback:server>
      <pingback:target>http://t-sql.ru/post.aspx?id=02faaa09-e03b-45f8-9dd8-6bc219c70beb</pingback:target>
      <slash:comments>5</slash:comments>
      <trackback:ping>http://t-sql.ru/trackback.axd?id=02faaa09-e03b-45f8-9dd8-6bc219c70beb</trackback:ping>
      <wfw:comment>http://t-sql.ru/post/xp_servicecontrol.aspx#comment</wfw:comment>
      <wfw:commentRss>http://t-sql.ru/syndication.axd?post=02faaa09-e03b-45f8-9dd8-6bc219c70beb</wfw:commentRss>
    </item>
    <item>
      <title>Live Query Statistics</title>
      <description>&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fMicrosoft_SQL_Server_2014_logo.jpg" alt="" align="left" /&gt;&lt;/p&gt;
&lt;p&gt;В родном клиенте &lt;strong&gt;SQL Server Management Studio 2016&lt;/strong&gt; появилась возможность в режиме реального времени просматривать, как выполняется запрос. Отслеживать построение плана и оперативно оптимизировать его.&lt;/p&gt;
&lt;p&gt;Функционал поддерживается, как для новой версии SQL Server 2016, так и для SQL Server 2014 SP1.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;В графическом виде можно видеть, как выполняется запрос:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2flive_execution_plans.gif" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fThing1_Progress.gif" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fshort_query2.gif" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Просмотреть live query statistics можно несколькими способами:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fIC752395.jpg.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fIC752396.jpg.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fIC752398.jpg.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Кроме того, можно включить настройки SET STATISTICS XML ON или SET STATISTICS PROFILE ON, прежде чем запустить выполнение запроса. А в другой сессии выполнить запрос к системному представлению &lt;a href="https://msdn.microsoft.com/ru-ru/library/dn223301(v=sql.120).aspx"&gt;sys.dm_exec_query_profiles&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;select st.text
, eqp.physical_operator_name
, eqp.row_count
, eqp.estimate_row_count
, 100 * eqp.row_count /eqp.estimate_row_count as [PercentComplete]
  from sys.dm_exec_query_profiles as eqp
    cross apply sys.dm_exec_sql_text (eqp.sql_handle) as st
&lt;/pre&gt;
&lt;p&gt;Либо использовать &lt;a href="https://msdn.microsoft.com/en-us/library/bb630319.aspx"&gt;расширенное событие (Extended Events)&lt;/a&gt; - &lt;strong&gt;query_post_execution_showplan&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt; Ссылки по теме:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://msdn.microsoft.com/en-us/library/dn831878.aspx"&gt;https://msdn.microsoft.com/en-us/library/dn831878.aspx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.brentozar.com/archive/2015/05/announcing-live-query-execution-plans/"&gt;http://www.brentozar.com/archive/2015/05/announcing-live-query-execution-plans/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.alexvolok.com/2015/07/3-good-things-about-live-query-statistics/"&gt;http://www.alexvolok.com/2015/07/3-good-things-about-live-query-statistics/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <link>http://t-sql.ru/post/Live_Query_Statistics.aspx</link>
      <author>a.knyazev@t-sql.ru</author>
      <comments>http://t-sql.ru/post/Live_Query_Statistics.aspx#comment</comments>
      <guid>http://t-sql.ru/post.aspx?id=029df161-e713-43a4-8024-bec0cca3f35f</guid>
      <pubDate>Wed, 19 Aug 2015 03:40:00 +0800</pubDate>
      <category>SQL Server</category>
      <dc:publisher>Alexey Knyazev</dc:publisher>
      <pingback:server>http://t-sql.ru/pingback.axd</pingback:server>
      <pingback:target>http://t-sql.ru/post.aspx?id=029df161-e713-43a4-8024-bec0cca3f35f</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://t-sql.ru/trackback.axd?id=029df161-e713-43a4-8024-bec0cca3f35f</trackback:ping>
      <wfw:comment>http://t-sql.ru/post/Live_Query_Statistics.aspx#comment</wfw:comment>
      <wfw:commentRss>http://t-sql.ru/syndication.axd?post=029df161-e713-43a4-8024-bec0cca3f35f</wfw:commentRss>
    </item>
    <item>
      <title>SQL Server 2016: Новые ON-Line операции</title>
      <description>&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fMicrosoft_SQL_Server_2014_logo.jpg" alt="" align="left" /&gt;С выходом каждой новой версии SQL Server появляется всё больше операций, которые могут быть проведены ON-Line, т.е. без длительных блокировок и ожиданий. В SQL Server 2014, например,&amp;nbsp;мы увидели &lt;a href="http://t-sql.ru/post/low_priority_lock_wait.aspx"&gt;ON-Line операции над отдельными секциями секционированных объектов&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Новая версия SQL Server 2016 так же добавит несколько операций ON-Line.&lt;/p&gt;
&lt;p&gt;Во первых появится возможность совершать операцию &lt;a href="https://msdn.microsoft.com/ru-ru/library/ms177570(v=sql.120).aspx"&gt;TRUNCATE&lt;/a&gt; над отдельными секциями, а не только над всей таблицей. О преимуществах операции TRUNCATE над операцией DELETE я не буду останавливать в этой статье, просто скажу, что за счёт минимального количества операций протоколирования, операция TRUCATE выполняется в разы быстрее, чем операция DELETE. При этом мы можем указывать не только отдельную секцию, но и целый диапазон.&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;truncate table dbo.test_table with ( partitions ( 1, 3 to 4 ) ); 
go
&lt;/pre&gt;
&lt;p&gt;А вторая операция - это возможность выполнять изменение колонки в таблице в режиме ON-Line&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;alter table dbo.test_table 
alter column val varchar(50) not null 
with (online = on );
go
&lt;/pre&gt;
&lt;p&gt;Для демонстрации TRUNCATE над отдельными секция создадим секционированную таблицу и наполним её данными:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;create partition function pf_dt ( datetime )
as range right for values ( '20150801', '20150802', '20150803', '20150804', '20150805' );
go
 
create partition scheme ps_dt
as partition pf_dt all to ( [primary] );
go
 
create table dbo.test_table ( dt datetime, val varchar(50) ) on ps_dt (dt);
go
 
insert into dbo.test_table
select '20150801', replicate( 'A', 50 );
go 10
insert into dbo.test_table
select '20150802', replicate( 'A', 50 );
go 10
insert into dbo.test_table
select '20150803', replicate( 'A', 50 );
go 10
insert into dbo.test_table
select '20150804', replicate( 'A', 50 );
go 10
insert into dbo.test_table
select '20150805', replicate( 'A', 50 );
go 10
&lt;/pre&gt;
&lt;p&gt;Убедимся, что в секциях появились данные:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;select partition_number, rows 
from sys.partitions
where object_id = object_id ( 'dbo.test_table' ); 
go
&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2ftruncate01.PNG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Теперь выполним TRUNCATE над секциями 2 и 4-5, и убедимся, что данные удалились:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;truncate table dbo.test_table with ( partitions ( 2, 4 to 5 ) );
go
select partition_number, rows 
from sys.partitions
where object_id = object_id ( 'dbo.test_table' ); 
go
&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2ftruncate02.PNG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt; А теперь протестируем, как работает On-Line операция изменения колонки. Создадим таблицу с большой колонкой, чтобы каждая запись занимала отдельную страницу и наполним её данными:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;create table dbo.test_table ( id int identity primary key, val varchar(8000) );
go
insert into dbo.test_table
select replicate( 'A', 8000 ) from sys.all_columns;
go 100
&lt;/pre&gt;
&lt;p&gt;Теперь попробуем изменить колонку val на NOT NULL, а в другом окне будем просматривать данные в таблице. Можно убедиться, что, когда мы делаем ALTER COLUMN в режиме ON-Line, то данные остаются доступны на чтение, а блокировка схемы Sch-M накладывается лишь в самом конце операции ALTER, когда происходит переключение на новые страницы с данными. При этом доступны не только сами данные, но и статистики, которые были созданы по этому полю и лишь после того, как данные колонки переключаются на новые страницы, статистика удаляется и её необходимо создать по новой. Для того, чтобы убедиться, что после ON-Line операции ALTER COLUMN изменились страницы выполним следующий скрипт:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;drop table dbo.test_table;
go
create table dbo.test_table ( id int identity primary key, val varchar(8000) );
go
insert into dbo.test_table
select replicate( 'A', 8000 );
go
select l.page_id from dbo.test_table as t
  outer apply sys.fn_PhysLocCracker(%%PhysLoc%%) as l;
go
alter table dbo.test_table 
alter column val varchar(8000) not null 
--with (online = on );
go
select l.page_id from dbo.test_table as t
  outer apply sys.fn_PhysLocCracker(%%PhysLoc%%) as l;
go
-------------------------------------
drop table dbo.test_table;
go
create table dbo.test_table ( id int identity primary key, val varchar(8000) );
go
insert into dbo.test_table
select replicate( 'A', 8000 );
go
select l.page_id from dbo.test_table as t
  outer apply sys.fn_PhysLocCracker(%%PhysLoc%%) as l;
go
alter table dbo.test_table 
alter column val varchar(8000) not null 
with (online = on );
go
select l.page_id from dbo.test_table as t
  outer apply sys.fn_PhysLocCracker(%%PhysLoc%%) as l;
go&lt;/pre&gt;
&lt;p&gt;Результат ниже:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2falter.PNG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlperformance.com/2015/02/sql-performance/more-online-operations"&gt;Подробнее про On-Line операцию ALTER COLUMN&lt;/a&gt;&lt;/p&gt;</description>
      <link>http://t-sql.ru/post/sqlserver2016_online.aspx</link>
      <author>a.knyazev@t-sql.ru</author>
      <comments>http://t-sql.ru/post/sqlserver2016_online.aspx#comment</comments>
      <guid>http://t-sql.ru/post.aspx?id=44ee660a-d462-4817-b5d9-1411a61ac396</guid>
      <pubDate>Sun, 02 Aug 2015 03:10:00 +0800</pubDate>
      <category>SQL Server</category>
      <dc:publisher>Alexey Knyazev</dc:publisher>
      <pingback:server>http://t-sql.ru/pingback.axd</pingback:server>
      <pingback:target>http://t-sql.ru/post.aspx?id=44ee660a-d462-4817-b5d9-1411a61ac396</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://t-sql.ru/trackback.axd?id=44ee660a-d462-4817-b5d9-1411a61ac396</trackback:ping>
      <wfw:comment>http://t-sql.ru/post/sqlserver2016_online.aspx#comment</wfw:comment>
      <wfw:commentRss>http://t-sql.ru/syndication.axd?post=44ee660a-d462-4817-b5d9-1411a61ac396</wfw:commentRss>
    </item>
    <item>
      <title>SQL Server 2016: Row-Level Security</title>
      <description>&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fMicrosoft_SQL_Server_2014_logo.jpg" alt="" align="left" /&gt; Одна из интересных новинок в SQL Server 2016 - это Row-Level Security (&lt;strong&gt;RLS&lt;/strong&gt;). Технология RLS (row-level security или безопасность на уровне строк) предоставляет возможность создания политик безопасности, которые ограничивают доступ пользователям к информации в БД.&lt;/p&gt;
&lt;p&gt;Данная технология поддерживается во многих современных СУБД, но, к сожалению, в предыдущих версиях SQL Server реализовать RLS было не самой простой задачей. На сайте Microsoft есть целый документ, как это реализовать - &lt;a href="https://archive.codeplex.com/?p=sqlserverlst"&gt;http://download.microsoft.com/download/8/8/0/880F282A-AA4E-4351-83C0-DFFA3B56A19E/SQL_Server_RLS-CLS_White_paper.docx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Теперь рассмотрим, как это реализовано в SQL Server 2016&lt;/p&gt;
&lt;p&gt;Создадим тестовую таблицу и наполним её данными:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;if object_id ( N'dbo.TestRLS', N'U' ) is not null
drop table dbo.TestRLS;
go
create table dbo.TestRLS ( id int identity
                         , UserName sysname
                         , Val int
                         );
go
insert dbo.TestRLS 
values  ( 'User1', 11 ) 
      , ( 'User1', 12 )
      , ( 'User1', 13 )
      , ( 'User2', 21 )
      , ( 'User2', 22 )
      ;
go
select * from dbo.TestRLS;
go
&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fRLS02.PNG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Технология RLS состоит из 3-х компонентов: &lt;br /&gt; &lt;strong&gt;Predicate function&lt;/strong&gt; - Пользовательская функция описывает логику безопасности &lt;br /&gt; &lt;strong&gt;Security predicate&lt;/strong&gt; - Применяет предикат к конкретной таблице. Два типа: filter predicates and blocking predicates &lt;br /&gt; &lt;strong&gt;Security policy&lt;/strong&gt; - Коллекция предикатов для нескольких таблиц&lt;/p&gt;
&lt;p&gt;Теперь создадим 2-х пользователей и дадим им права на чтение нашей таблицы&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;create user User1 without login;
create user User2 without login;
go
grant select on dbo.TestRLS to User1;
grant select on dbo.TestRLS to User2;
go
&lt;/pre&gt;
&lt;p&gt;Создадим функцию (Predicate function), которая будет определять права&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;create function dbo.fn_securitypredicate(@user_name as sysname)
    returns table
with schemabinding
as
    return select 1 as fn_securitypredicate_result 
      where @user_name = user_name();
go
&lt;/pre&gt;
&lt;p&gt;И теперь по имени пользователя будем определять, какие данные нам доступны:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;create security policy rls_plicy
add filter predicate dbo.fn_securitypredicate(UserName) 
on dbo.TestRLS
with (state = on);
go
&lt;/pre&gt;
&lt;p&gt;Посмотрим, какие данные видны в контексте каждого пользователя:&lt;/p&gt;
&lt;pre class="brush: sql;"&gt;--Текущий пользователь
select user_name() as [user_name];
go
select * from dbo.TestRLS;
go

--Перевлючаем в контекст пользователя User1
execute as user = 'User1';
go
select user_name() as [user_name];
go
select * from dbo.TestRLS;
go
revert;
go

--Перевлючаем в контекст пользователя User2
execute as user = 'User2';
go
select user_name() as [user_name];
go
select * from dbo.TestRLS;
go
revert;
go
&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://t-sql.ru/image.axd?picture=%2f2015%2f11%2fRLS03.PNG" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Всё достаточно легко и просто!&lt;/p&gt;</description>
      <link>http://t-sql.ru/post/rls.aspx</link>
      <author>a.knyazev@t-sql.ru</author>
      <comments>http://t-sql.ru/post/rls.aspx#comment</comments>
      <guid>http://t-sql.ru/post.aspx?id=359d10e8-40d7-4da6-9ad3-4ccfc98c20a0</guid>
      <pubDate>Fri, 03 Jul 2015 02:48:00 +0800</pubDate>
      <category>SQL Server</category>
      <dc:publisher>Alexey Knyazev</dc:publisher>
      <pingback:server>http://t-sql.ru/pingback.axd</pingback:server>
      <pingback:target>http://t-sql.ru/post.aspx?id=359d10e8-40d7-4da6-9ad3-4ccfc98c20a0</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://t-sql.ru/trackback.axd?id=359d10e8-40d7-4da6-9ad3-4ccfc98c20a0</trackback:ping>
      <wfw:comment>http://t-sql.ru/post/rls.aspx#comment</wfw:comment>
      <wfw:commentRss>http://t-sql.ru/syndication.axd?post=359d10e8-40d7-4da6-9ad3-4ccfc98c20a0</wfw:commentRss>
    </item>
  </channel>
</rss>