Ошибка: Программе установки SQL Server не удалось получить сведения о системной учетной записи ASPNET

by Alexey Knyazev 31. июля 2010 21:21

При установке SQL Server Express возникает ошибка:

Программе установки SQL Server не удалось получить сведения о системной учетной записи для учетной записи ASPNET. Чтобы продолжить, переустановите платформу .NET Framework, а затем снова запустите программу установки SQL Server.


Английский вариант:
SQL Server Setup failed to obtain system account information for the ASPNET account. To proceed, reinstall the .NET Framework, and then run SQL Server Setup again.


Лекарство:

Запускаем CMD:


cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
aspnet_regiis -i

После создания ASPNET-учётной записи, можно повторно запускать установку SQL Server.

Tags: ,

SQL Server

SQL Server требует постоянно перезагрузку

by Alexey Knyazev 13. июня 2010 21:48

Ошибка с которой и мне пришлось столкнуться, при установке SQL Server либо SP, требовалась перезагрузка, но после перезагрузки сообщение появлялось опять:

Rule "Restart computer" failed.
A computer restart is required. You must restart this computer before installing SQL Server.

Решается проблема достаточно просто, правкой реестра: Находим ветку "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations" и удаляем или переименовываем ключ PendingFileRenameOperations

 

Этого должно быть достаточно, но если и это не поможет, то проделайте теже действия с ключами ещё пары веток реестра:

  • "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet001\Control\Session Manager\PendingFileRenameOperations"
  • "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet002\Control\Session Manager\PendingFileRenameOperations"

После этого можно продолжить установку SQL Server.

Tags: , ,

SQL Server

Дата прописью

by Alexey Knyazev 14. апреля 2010 18:31

Делал для себя, но возможно ещё кому-то пригодится:

--Создание функции
CREATE FUNCTION DBO.GetDateWord 
(
@dt DATETIME
)
RETURNS NVARCHAR(100)
AS
BEGIN
DECLARE @str NVARCHAR(100)

SELECT 
@str=CASE DATEPART(dd, @dt)
WHEN 1 THEN 'Первого '
WHEN 2 THEN 'Второго '
WHEN 3 THEN 'Третьего '
WHEN 4 THEN 'Четвертого '
WHEN 5 THEN 'Пятого '
WHEN 6 THEN 'Шестого '
WHEN 7 THEN 'Седьмого '
WHEN 8 THEN 'Восьмого '
WHEN 9 THEN 'Девятого '
WHEN 10 THEN 'Десятого '
WHEN 11 THEN 'Одиннадцатого '
WHEN 12 THEN 'Двенадцатого '
WHEN 13 THEN 'Тринадцатого '
WHEN 14 THEN 'Четырнадцатого '
WHEN 15 THEN 'Пятнадцатого '
WHEN 16 THEN 'Шестнадцатого '
WHEN 17 THEN 'Семнадцатого '
WHEN 18 THEN 'Восемнадцатого '
WHEN 19 THEN 'Девятнадцатого '
WHEN 20 THEN 'Двадцатого '
WHEN 21 THEN 'Двадцать первого '
WHEN 22 THEN 'Двадцать второго '
WHEN 23 THEN 'Двадцать третьего '
WHEN 24 THEN 'Двадцать четвертого '
WHEN 25 THEN 'Двадцать пятого '
WHEN 26 THEN 'Двадцать шестого '
WHEN 27 THEN 'Двадцать седьмого '
WHEN 28 THEN 'Двадцать восьмого '
WHEN 29 THEN 'Двадцать девятого '
WHEN 30 THEN 'Тридцатого '
WHEN 31 THEN 'Тридцать первого '
END
+
CASE DATEPART(mm, @dt)
WHEN 1 THEN 'января'
WHEN 2 THEN 'февраля'
WHEN 3 THEN 'марта'
WHEN 4 THEN 'апреля'
WHEN 5 THEN 'мая'
WHEN 6 THEN 'июня'
WHEN 7 THEN 'июля'
WHEN 8 THEN 'августа'
WHEN 9 THEN 'сентября'
WHEN 10 THEN 'октября'
WHEN 11 THEN 'ноября'
WHEN 12 THEN 'декабря'
END
+' '+
CASE LEFT(DATEPART(yy, @dt),2)
WHEN 19 THEN 'одна тысяча девятьсот '
WHEN 20 THEN 'две тысячи '
WHEN 21 THEN 'две тысячи сто '
END
+
CASE WHEN RIGHT(DATEPART(yy, @dt), 2) IN 
(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 40, 50, 60, 70, 80, 90)
THEN 
CASE RIGHT(DATEPART(yy, @dt), 2)
WHEN 10 THEN 'десятого'
WHEN 11 THEN 'одиннадцатого'
WHEN 12 THEN 'двенадцатого'
WHEN 13 THEN 'тринадцатого'
WHEN 14 THEN 'четырнадцатого'
WHEN 15 THEN 'пятнадцатого'
WHEN 16 THEN 'шестнадцатого'
WHEN 17 THEN 'семнадцатого'
WHEN 18 THEN 'восемнадцатого'
WHEN 19 THEN 'девятнадцатого'
WHEN 20 THEN 'двадцатого'
WHEN 30 THEN 'трицатого'
WHEN 40 THEN 'сорокового'
WHEN 50 THEN 'пятидесятого'
WHEN 60 THEN 'шестидесятого'
WHEN 70 THEN 'семидесятого'
WHEN 80 THEN 'восьмидесятого'
WHEN 90 THEN 'девяностого'
END

ELSE 

CASE RIGHT (DATEPART(yy, @dt),2)/10
WHEN 2 THEN 'двадцать'
WHEN 3 THEN 'тридцать'
WHEN 4 THEN 'сорок'
WHEN 5 THEN 'пятьдесят'
WHEN 6 THEN 'шестьдесят'
WHEN 7 THEN 'семьдесят'
WHEN 8 THEN 'восемьдесят'
WHEN 9 THEN 'девяносто'
END
+
CASE RIGHT (DATEPART(yy, @dt),1)
WHEN 1 THEN 'первого'
WHEN 2 THEN 'второго'
WHEN 3 THEN 'третьего'
WHEN 4 THEN 'четвертого'
WHEN 5 THEN 'пятого'
WHEN 6 THEN 'шестого'
WHEN 7 THEN 'седьмого'
WHEN 8 THEN 'восьмого'
WHEN 9 THEN 'девятого'
END

END 
+' года'


RETURN @str

END

 

--Тестируем:
SELECT dbo.GetDateWord(GETDATE())

Ну и результат работы:

Четырнадцатого апреля две тысячи десятого года

PS: Набор функций для создания суммы прописью

Tags: , ,

SQL Server

Отправка почты SMTP (очередная сборка)

by Alexey Knyazev 7. апреля 2010 10:15

В очередной раз обращаюсь к работе с почтой через CLR-сборки. Я уже описывал, как читать почту по протоколу POP3 и IMAP. Теперь небольшая демонстрация, как отправлять почту через SMTP.

SMTP (англ. Simple Mail Transfer Protocol — простой протокол передачи почты) — это сетевой протокол, предназначенный для передачи электронной почты в сетях TCP/IP.

Для отправки почты в SQL Server 2005 и выше используется Компонент Database Mail.

Компонент Database Mail — это решение уровня предприятия для отправки сообщений электронной почты от компонента SQL Server Database Engine. Используя компонент Database Mail, приложения базы данных могут отправлять почтовые сообщения пользователям. Сообщения могут содержать результаты запроса, а также могут включать файлы из любого сетевого ресурса. Компонент Database Mail спроектирован для надежности, масштабируемости, безопасности и простой поддержки.

А я покажу простенький код сборки для отправки почты, не используя Database Mail.

Код сборки:

using System;
using System.Net;
using System.Net.Mail;

public class SMTPClr
{
    public static void SendMessage(string From, string To, string Subject, string Body, string Host, string UserName, string Password)
    {
        MailMessage mes = new MailMessage(From, To, Subject, Body);
        SmtpClient client = new SmtpClient(Host); 
        client.Credentials = new NetworkCredential(UserName, Password); 
        client.Send(mes);
    }
}

 

Вот и всё!!! Smile

Далее регистрируем сборку и отправляем тестовое письмо:

--Регистрируем сборку
CREATE ASSEMBLY SMTPCLR
FROM 'C:\SMTPClr\SMTPCLR.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS;
GO

--Создаём процедуру отправки почты
CREATE PROCEDURE SendMessage
(
--От кого
@From nvarchar(max),
--Кому
@To nvarchar(max),
--Тема письма
@Subject nvarchar(max),
--Само сообщение
@Body nvarchar(max),
--Имя сервера или его IP (порт 25)
@Host nvarchar(max),
--Имя пользователя
@UserName nvarchar(max),
--Пароль
@Password nvarchar(max)
) 
AS 
EXTERNAL NAME SMTPCLR.SMTPClr.SendMessage
GO

--Отправляем письмо
EXECUTE SendMessage 'admin@microsoft.com', 'a.knyazev@t-sql.ru', 'SMTPClr', 'Hi, Alexey!', 'MySMTPServer', 'MySMTPUserName', 'MySMTPPassword'

И не забываем предварительно включить возможность работы с CLR-сборками:

--Включаем выполнение пользовательских сборок
SP_CONFIGURE 'clr enabled', 1
GO
RECONFIGURE
GO


--Модули базы данных (например, пользовательские функции или хранимые процедуры),
--которые используют контекст олицетворения, могут обращаться к ресурсам,
--находящимся вне базы данных.
ALTER DATABASE [Ваша БД] SET TRUSTWORTHY ON
GO

Tags: ,

SQL Server

Мой SQL Server отличный переводчик

by Alexey Knyazev 17. марта 2010 09:42

Совсем недавно у меня появилась безумная идея: как организовать автоматический перевод текстов внутри сервера БД.

Возможно, это глупо перекладывать такую логику и задачу на SQL Server, т.к. он предназначен совсем для других целей...но, согласитесь, как было бы здорово, если бы наш сервер сам переводил наши данные на другой язык либо динамически либо по расписанию, пусть даже это будет машинный перевод. Прежде чем приступить к реализации этого безумия, я стал искать какие переводчики доступны в сети, главные критери: бесплатный и более или менее читабельный перевод.

Мой выбор пал на переводчик Microsoft® Translator (http://www.microsofttranslator.com/)

 

 

 

 На странице этого переводчика есть возможность переводить тексты on-line:

 

Но самое главное, что Microsoft предлагает богатый набор инструментов для интеграции переводчика в наши системы (http://www.microsofttranslator.com/Tools/)

 

Microsoft Translator Interactive SDK (http://sdk.microsofttranslator.com/) содержит примеры, как можно работать с этим инструментом:

 

Меня интересует SOAP Interface, пару месяцев назад я писал, как можно работать с Web-службами через CLR (http://www.t-sql.ru/post/WebCLR.aspx), но прежде чем начать писать сборку для перевода текстов внутри БД, необходимо зарегистрировать (если вы ещё этого не сделали) AppID (http://www.bing.com/developers/createapp.aspx), который открывает вам доступ к богатому набору инструментов, в том числе и доступ к Microsoft Translator.

После регистрации и активации AppID, можем переходить к разработке нашей сборки, примеры работы с Web-службой описаны на странице Microsoft Translator Interactive SDK.

Для начала создадим прокси-сборку, для этого необходимо выполнить команду:

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\wsdl.exe" /o:Translator.cs /n:WS http://api.microsofttranslator.com/V1/Soap.svc

Для удобства, я создал отдельную папку C:\Translator, и в ней создал BAT-ник с этой командой. После запуска этого батника в папке появился файл Translator.cs.

Теперь создадим наш класс, из которого будет сделана наша сборка: TranslatorCLR.cs

using System;
using Microsoft.SqlServer.Server;
using System.Data;
using System.Data.SqlTypes;
using System.Collections;
using WS;

public class WSClass
{
  	[SqlFunction(FillRowMethodName = "FillRow",
        	TableDefinition = "Lng nvarchar(10), Language nvarchar(100)")
    	]

//Получаем список доступных языков
public static IEnumerable GetLanguages(String AppID, string locale)
{
	ArrayList Rows = new ArrayList();
        WS.Soap lsc = new WS.Soap();
	string[] s1=lsc.GetLanguages(AppID);
	string[] s2=lsc.GetLanguageNames(AppID, locale);

	for(int i = 0; i<=s1.Length-1; i++)
	{
	Rows.Add(new object[] {s1[i], s2[i]});
	}

        return Rows;
}

public static void FillRow(
                        Object row,
                        out string Lng, out string Language)
{
	object[] xrow = (object[])row;
	Lng = (string)xrow[0];
	Language = (string)xrow[1];
}

//Перевод текста
public static string Translate(String AppID, string InputStr, string forLanguage, string toLanguage)
{

        WS.Soap lsc = new WS.Soap();
	string s=lsc.Translate(AppID, InputStr, forLanguage, toLanguage);
        return s;
}

//Определение на каком языке текст
public static string Detect(String AppID, string InputStr)
{

        WS.Soap lsc = new WS.Soap();
	string s=lsc.Detect(AppID, InputStr);
        return s;
}

}

Теперь на базе 2х классов можем создать нашу сборку, для этого создаю ещё один батник с кодом

"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CSC" /target:library /out:TranslatorWS.dll *.cs

На выходе получаем библиотеку TranslatorWS.dll.

Последний шаг-создаём сборку сериализации XML для типов в нашей сборке, для этого я опять делаю батник с текстом:

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\sgen.exe" /a:TranslatorWS.dll

На выходе ещё одна библиотека: TranslatorWS.XmlSerializers.dll

Теперь регистрируем наши сборки в БД, создаём функции и начинаем работать:

CREATE DATABASE TestDB
GO

ALTER DATABASE TestDB SET TRUSTWORTHY ON
GO

USE TestDB
GO

CREATE ASSEMBLY ClrWebServices
FROM 'C:\Translator\TranslatorWS.dll'
WITH PERMISSION_SET = UNSAFE;
GO

CREATE ASSEMBLY [ClrWebServices.XmlSerializers]
FROM 'C:\Translator\TranslatorWS.XmlSerializers.dll'
WITH PERMISSION_SET = SAFE;
GO

CREATE FUNCTION [dbo].[GetLanguages]
(
@AppID nvarchar(40),
@locale nvarchar(10)
)
RETURNS TABLE
(
Lng nvarchar(10),
Language nvarchar(100)
)
AS
EXTERNAL NAME [ClrWebServices].[WSClass].[GetLanguages]
GO

CREATE FUNCTION [dbo].[Translate]
(
@AppID nvarchar(40),
@InputStr nvarchar(max),
@forLanguage nvarchar(5),
@toLanguage nvarchar(5)
)
RETURNS nvarchar(MAX)
AS
EXTERNAL NAME [ClrWebServices].[WSClass].[Translate]
GO

CREATE FUNCTION [dbo].[Detect]
(
@AppID nvarchar(40),
@InputStr nvarchar(max)
)
RETURNS nvarchar(MAX)
AS
EXTERNAL NAME [ClrWebServices].[WSClass].[Detect]
GO

Для начала получим список доступных языков:

SELECT * from [dbo].[GetLanguages] ('****************************', 'ru')

Где вместо звёздочек вы указываете ваш AppID, а 2ой параметр-это язык на которов вы хотите получить описание доступных языков, на выходе вот такая табличка:

  1. ar арабский
  2. bg болгарский
  3. zh-CHS китайский упрощенный
  4. zh-CHT китайский традиционный
  5. cs чешский
  6. da датский
  7. nl нидерландский
  8. en английский
  9. ht Гаитянский
  10. fi финский
  11. fr французский
  12. de немецкий
  13. el греческий
  14. he иврит
  15. hu венгерский
  16. it итальянский
  17. ja японский
  18. ko корейский
  19. lt литовский
  20. no норвежский
  21. pl польский
  22. pt португальский
  23. ro румынский
  24. ru русский
  25. sk словацкий
  26. sl словенский
  27. es испанский
  28. sv шведский
  29. th тайский
  30. tr турецкий

На момент написания этого поста, было доступно 30 языков.

Следующим примером я покажу, как определить на каком языке текст, для этого создам таблицу с 2мя записями на русском и английском и запустим нашу функцию:

DECLARE @s TABLE (val varchar(max))
INSERT INTO @s
SELECT 'Enter some text for the language you want detected'
UNION ALL
SELECT 'Шла Cаша по шоссе'

SELECT *, [dbo].[Detect]('****************************', val) FROM @s

Результат:

 

Ну и собственно, сам перевод данных:

DECLARE @s nvarchar(max)
SET @s='With upcoming release of the latest version of Microsoft SQL Server, SQL Server 2008 R2, Microsoft continues to build on the Information Platform Vision by enabling businesses to deliver near real-time information through rich applications. Not only does SQL Server offers a complete approach to managing, accessing and delivering information across the organization; but now the power of SQL Server is extending to the Cloud through SQL Azure. SQL Azure provides a consistent program model and common tools while offering new business opportunities, high availability, and massive scale through distributed data services.
People are at the center of the Information Platform – IT and Database professionals who support the expanding needs of the business, Developers who build solutions quickly to capture business opportunities and End users who are looking to quickly mine volumes of data for business insights. SQL Server 2008 R2 delivers something unique and empowering to each of these contributors.
'

SELECT [dbo].[Translate] ('****************************', @s, 'en', 'ru')

Результат перевода можете оценить сами:

С предстоящем выпуске последней версии Microsoft SQL Server, SQL Server 2008 R2, Майкрософт продолжает опираться на информационной платформы видение, позволяя предприятиям для доставки вблизи реального времени информацию с помощью многофункциональных приложений. Не только делает SQL Server предлагает полный подход к управлению, доступ к и доставки информации по организации; но теперь власть SQL Server расширение в облаке через SQL лазурь. Лазурный SQL предоставляет модель последовательной программы и общие инструменты предлагая новые бизнес-возможности, высокая доступность и массовом масштабе путем распределенных данных услуг. Люди, в центре платформы информации – база данных и ИТ специалистов, которые поддерживают расширение потребностей бизнеса, разработчики, которые создают решения быстро захватить бизнес-возможности и конечных пользователей, которые хотят быстро шахты объемы данных для бизнес-идеи. SQL Server 2008 R2 обеспечивает что-то уникальное и расширение прав и возможностей для каждого из этих вкладчиков..

Tags: , , , ,

SQL Server

Выборка из однотипных тaблиц (разные схемы)

by Alexey Knyazev 15. марта 2010 09:34

Начиная с 2005ой версии в SQL Server появилось такое понятие как схема. Схема формально определяется как набор объектов в базе данных, объединенных общим пространством имен. Проще всего представить себе схему как некий логический контейнер в базе данных, которому могут принадлежать таблицы, представления, хранимые процедуры, пользовательские функции, ограничения целостности, пользовательские типы данных и другие объекты базы данных. Этот контейнер удобно использовать как для именования объектов и их логической группировки, так и для предоставления разрешений. Например, если в базе данных есть набор таблиц с финансовой информацией, удобно поместить их в одну схему и предоставлять пользователям разрешения на эту схему (т. е. на этот набор таблиц).

Но возможно вам потребуедся сделать выборку из однотипных таблиц с одинаковым именем, но расположенных в разных схемах. Стандартного средства в T-SQL нет, поэтому написал небольшой динамический скрипт, который выводит результат из нескольких таблиц в виде одного рекордсета.

Для демонстрации создадим новую базу с 10ю разными схемами. Расположим в этих схемах несколько однотипных (имена так же совпадают) таблиц

--Контекст БД мастер
USE master
GO
--Проверяем наличие БД "TestDB" и если она существует-удаляем
IF (SELECT DB_ID('TestDB')) IS NOT NULL
DROP DATABASE TestDB
GO
--Создаём новую БД "TestDB"
CREATE DATABASE TestDB
GO
--Переходим в неё
USE TestDB
GO
--Создаём 10 схем
CREATE SCHEMA Shema1
GO
CREATE SCHEMA Shema2
GO
CREATE SCHEMA Shema3
GO
CREATE SCHEMA Shema4
GO
CREATE SCHEMA Shema5
GO
CREATE SCHEMA Shema6
GO
CREATE SCHEMA Shema7
GO
CREATE SCHEMA Shema8
GO
CREATE SCHEMA Shema9
GO
CREATE SCHEMA Shema10
GO

--В этих схемах создаём однотипные таблицы,
--для наглядности данные содержат имя схемы, таблицы и значене Value"N"
CREATE TABLE Shema1.Table1 (val varchar(255))
INSERT INTO Shema1.Table1
SELECT 'Shema1.Table1_Value1'
UNION ALL
SELECT 'Shema1.Table1_Value2'
UNION ALL
SELECT 'Shema1.Table1_Value3'

CREATE TABLE Shema3.Table1 (val varchar(255))
INSERT INTO Shema3.Table1
SELECT 'Shema3.Table1_Value1'
UNION ALL
SELECT 'Shema3.Table1_Value2'

CREATE TABLE Shema10.Table1 (val varchar(255))
INSERT INTO Shema10.Table1
SELECT 'Shema10.Table1_Value1'
UNION ALL
SELECT 'Shema10.Table1_Value2'
UNION ALL
SELECT 'Shema10.Table1_Value3'
UNION ALL
SELECT 'Shema10.Table1_Value4'

CREATE TABLE Shema2.Table2 (val varchar(255))
INSERT INTO Shema2.Table2
SELECT 'Shema2.Table2_Value1'
UNION ALL
SELECT 'Shema2.Table2_Value2'
UNION ALL
SELECT 'Shema2.Table2_Value3'

CREATE TABLE Shema4.Table2 (val varchar(255))
INSERT INTO Shema4.Table2
SELECT 'Shema4.Table2_Value1'

CREATE TABLE Shema6.Table3 (val varchar(255))
INSERT INTO Shema6.Table3
SELECT 'Shema6.Table3_Value1'

CREATE TABLE Shema5.Table4 (val varchar(255))
INSERT INTO Shema5.Table4
SELECT 'Shema5.Table4_Value1'

CREATE TABLE Shema7.Table4 (val varchar(255))
INSERT INTO Shema7.Table4
SELECT 'Shema7.Table4_Value1'

CREATE TABLE Shema8.Table4 (val varchar(255))
INSERT INTO Shema8.Table4
SELECT 'Shema8.Table4_Value1'

CREATE TABLE Shema9.Table4 (val varchar(255))
INSERT INTO Shema9.Table4
SELECT 'Shema9.Table4_Value1'
UNION ALL
SELECT 'Shema9.Table4_Value2'

А теперь, указав на входе имя таблицы, выберим данные из таблиц с этим именем, но расположенных в разных схемах:

DECLARE @str NVARCHAR(MAX), @Table NVARCHAR(255)
SELECT @Table='Table1'

DECLARE Tables_cur CURSOR FOR
SELECT QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME=@Table

OPEN Tables_cur 

FETCH NEXT FROM Tables_cur INTO @Table

	WHILE (@@FETCH_STATUS!=-1) BEGIN
			IF (@@FETCH_STATUS!=-2)BEGIN
				SELECT @str=CASE WHEN @str IS NULL THEN 'SELECT * FROM '+@Table
				ELSE @str+ ' UNION ALL SELECT * FROM '+@Table END
			END
		FETCH NEXT FROM Tables_cur INTO @Table
	END

CLOSE Tables_cur
DEALLOCATE Tables_cur

EXECUTE (@str)

Результат этого запроса:

  1. Shema1.Table1_Value1
  2. Shema1.Table1_Value2
  3. Shema1.Table1_Value3
  4. Shema3.Table1_Value1
  5. Shema3.Table1_Value2
  6. Shema10.Table1_Value1
  7. Shema10.Table1_Value2
  8. Shema10.Table1_Value3
  9. Shema10.Table1_Value4

Запрос объеденил результат из 3х схем (Shema1, Shema3, Shema10), где таблица = 'Table1'.

Tags: , ,

SQL Server

Экспорт таблицы пользователей в АD (PоSh)

by Alexey Knyazev 10. марта 2010 09:25

На форуме "TechNet RUS SQL Forum" появился вопрос:

Можно ли сразу из БД при помощи MS SQL перевести значения полей в AD в виде пользователей. (К примеру по фамилии имеющихся в БД людей создать пользователей в AD с логином <фамилия>)? (http://social.technet.microsoft.com/Forums/ru-RU/sqlru/thread/54ca41d0-d70c-4318-8b5c-daa7aecce9f5)

В качестве решения подобной задачи предлагаю небольшой скрипт на PowerShell.

Для начала создадим тестовую таблицу в БД с Логином и Паролей пользователей (для демонстрации всего 5 юзеров):

CREATE TABLE Users (UserLogin sysname, UserPassword nvarchar(255))
GO

INSERT INTO Users
SELECT 'SQLUser1', '1234567890'
UNION ALL
SELECT 'SQLUser2', '1234567890'
UNION ALL
SELECT 'SQLUser3', '1234567890'
UNION ALL
SELECT 'SQLUser4', '1234567890'
UNION ALL
SELECT 'SQLUser5', '1234567890

Для работы с AD буду использовать бесплатный набор командлетов (часто называемых также AD cmdlets или QAD cmdlets), доступный с сайта http://www.quest.com/activeroles_server/arms.aspx.

А для создания пользователя команду New-QADUser, полный синтаксис команды доступен в wiki: http://wiki.powergui.org/index.php/New-QADUser

$Domen = "MyServerAD" #Read-Host "Введите адресс контролера"
$User = "MyUser" #read-host "Введите логин"
$Password =read-host "Введите пароль" -AsSecureString;

#Подключаемся к AD
Connect-QADService -Service $Domen -ConnectionAccount $User  -ConnectionPassword $Password;

#Создаём подключение к серверу БД
$SQLConnection = new-object System.Data.SqlClient.SqlConnection("Data Source='MyServerBD';User='MyUser';password='MyPassword';")
#Запрос к таблице с Юзерами
$Query="select * from Test.dbo.Users"
$SQLConnection.Open()
$SQLCommand = New-Object System.Data.SqlClient.SqlCommand($Query, $SQLConnection)

$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]
$rdr=$SQLCommand.ExecuteReader()

#В цикле по всему рекордсету перебераю записи с юзерами
While($rdr.Read())
{
#Выводим логин
Write-Host $rdr[0]
#Создаём пользователя в AD
New-QADUser -Name $rdr[0] -ParentContainer "MyServerAD.com/Users"  -SamAccountName $rdr[0] -UserPassword $rdr[1]
}
#Закрываем подключение к Серверу БД
$SQLConnection.Close();
#Отключаемся от AD
Disconnect-QADService;

Скрипт достаточно примитивный, но работает и если его довести до ума, то можно в AD экспортировать и другую информацию о пользователе.

Ранее я писал, как с помощью PowerShell создать группы пользователей AD: http://www.t-sql.ru/post/ADGroupsPoSh.aspx

Tags: , , ,

PowerShell | SQL Server

Своё шифрование в SQL Server 2005 и выше

by Alexey Knyazev 9. марта 2010 08:57

Практически в любой отрасли существуют свои критические данные, которые требуют шифрования. Начиная с SQL сервера версии 6.x, для шифрования данных вы можете применять функцию ENCRYPT (в последних версия эта функция уже недоступна), которая использует тот же метод (шифрования), что и опция WITH ENCRYPTION.

Начиная с SQL Server 2000 появилась недокументированная функция PWDENCRYPT, которая возвращает Хэш пароля (PWDENCRYPT — это устаревшая функция, которая может не поддерживаться в будущих версиях SQL Server. Вместо этого используйте программу HASHBYTES. HASHBYTES предоставляет больше алгоритмов хэширования), а так же PWDCOMPARE - Хэширует пароль и сравнивает хэш с хэшем существующего пароля.

Для более сложного шифрования данных до версии SQL Server 2005 приходилось "изобретать велосипед", но начиная с 9ой версии шифрование и дешифровка стали встроенным функционалом. А в SQL Server 2008 появилось прозрачное шифрование.

Но в очередной раз попробуем изобрести велосипед и организовать своё шифрование данных в виде CLR-сборки.

В качестве алгоритма шифрования я использую RSA. Алгоритм используется в большом числе криптографических приложений. На 2009 год система шифрования на основе RSA считается надёжной, начиная с размера в 1024 бита.

За основу взят класс RSACryptoServiceProvider.

Код сборки на C#:

using System;
using Microsoft.SqlServer.Server;
using System.Collections;
using System.Security.Cryptography;
using System.Text;

public class RSACLR
{
    [SqlFunction(FillRowMethodName = "FillRow",
        TableDefinition = "publicAndPrivateKeys nvarchar(max), justPublicKey nvarchar(max)")
    ]

//Генерируем 2 ключа: закрытый с публичным и только публичный
    public static IEnumerable GenerateKeys(int KeySize)
    {
        ArrayList row = new ArrayList();
        RSACryptoServiceProvider RSAProvider = new RSACryptoServiceProvider(KeySize);
        row.Add(new object[] { RSAProvider.ToXmlString(true), RSAProvider.ToXmlString(false) });
        return row;
    }

    public static void FillRow(Object row, out string publicAndPrivateKeys, out string justPublicKey)
    {

        object[] xrow = (object[])row;
        publicAndPrivateKeys = (string)xrow[0];
        justPublicKey = (string)xrow[1];

    }

//Шифрование, на входе строка, размер ключа и открытый(публичный) ключ
    public static string EncryptString(string inputString, int dwKeySize,
                             string xmlString)
    {
        RSACryptoServiceProvider rsaCryptoServiceProvider =
                                      new RSACryptoServiceProvider(dwKeySize);
        rsaCryptoServiceProvider.FromXmlString(xmlString);
        int keySize = dwKeySize / 8;
        byte[] bytes = Encoding.UTF32.GetBytes(inputString);

        int maxLength = keySize - 42;
        int dataLength = bytes.Length;
        int iterations = dataLength / maxLength;
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i <= iterations; i++)
        {
            byte[] tempBytes = new byte[
                    (dataLength - maxLength * i > maxLength) ? maxLength :
                                                  dataLength - maxLength * i];
            Buffer.BlockCopy(bytes, maxLength * i, tempBytes, 0,
                              tempBytes.Length);
            byte[] encryptedBytes = rsaCryptoServiceProvider.Encrypt(tempBytes,
                                                                      true);

            Array.Reverse(encryptedBytes);

            stringBuilder.Append(Convert.ToBase64String(encryptedBytes));
        }
        return stringBuilder.ToString();
    }

//Расшифровка, на входе шифрованная строка, размер ключа и закрытый ключ
    public static string DecryptString(string inputString, int dwKeySize,
                             string xmlString)
    {
        RSACryptoServiceProvider rsaCryptoServiceProvider
                                 = new RSACryptoServiceProvider(dwKeySize);
        rsaCryptoServiceProvider.FromXmlString(xmlString);
        int base64BlockSize = ((dwKeySize / 8 ) % 3 != 0) ?
          (((dwKeySize / 8 ) / 3) * 4) + 4 : ((dwKeySize / 8 ) / 3) * 4;
        int iterations = inputString.Length / base64BlockSize;
        ArrayList arrayList = new ArrayList();
        for (int i = 0; i < iterations; i++)
        {
            byte[] encryptedBytes = Convert.FromBase64String(
                 inputString.Substring(base64BlockSize * i, base64BlockSize));

            Array.Reverse(encryptedBytes);
            arrayList.AddRange(rsaCryptoServiceProvider.Decrypt(
                                encryptedBytes, true));
        }
        return Encoding.UTF32.GetString(arrayList.ToArray(
                                  Type.GetType("System.Byte")) as byte[]);
    }
}

Как всегда минимум кода.

Теперь регистрируем нашу сборку и создаём на её основе 3 функции (получение ключей, шифрование и расшифровка):

--Включаем выполнение пользовательских сборок
SP_CONFIGURE 'clr enabled', 1
GO
RECONFIGURE
GO

--Создаём тестовую БД для демострации
CREATE DATABASE TestDB
GO

--Модули базы данных (например, пользовательские функции или хранимые процедуры),
--которые используют контекст олицетворения, могут обращаться к ресурсам,
--находящимся вне базы данных.
ALTER DATABASE TestDB SET TRUSTWORTHY ON
GO

--Переходим в нашу БД
USE TestDB
GO

--Регистрируем сборку
CREATE ASSEMBLY RSACLR
FROM 'C:\RSA\RSACLR.dll'
WITH PERMISSION_SET = UNSAFE;
GO

--Получение ключей
CREATE FUNCTION GenerateKeys(@KeySize int)
RETURNS TABLE
(
publicAndPrivateKeys NVARCHAR(max),
justPublicKey NVARCHAR(max)
)
EXTERNAL NAME RSACLR.RSACLR.GenerateKeys;
GO

--Шифрование строки
CREATE FUNCTION EncryptString
(
@inputString nvarchar(MAX),
@dwKeySize int,
@xmlString nvarchar(MAX)
)
RETURNS nvarchar(MAX)
AS
EXTERNAL NAME RSACLR.RSACLR.EncryptString;
GO

--Расшифровка строки
CREATE FUNCTION DecryptString
(
@inputString nvarchar(MAX),
@dwKeySize int,
@xmlString nvarchar(MAX)
)
RETURNS nvarchar(MAX)
AS
EXTERNAL NAME RSACLR.RSACLR.DecryptString;
GO

Теперь продемонстрирую, как это работает:

--Создадим таблицу, в которой будут "жить" наши ключи
CREATE TABLE MyKeys(id int identity, publicAndPrivateKeys xml, justPublicKey xml)
--Добавим несколько ключей разной размерности
INSERT INTO MyKeys
SELECT * FROM GenerateKeys(512)
UNION ALL
SELECT * FROM GenerateKeys(1024)
UNION ALL
SELECT * FROM GenerateKeys(2048)

--и посмотрим в каком виде они у нас хранятся
SELECT * FROM MyKeys

Для наглядности я выбрал для хранения ключей тип XML

Теперь можно с помощью любой из пар ключей шифровать и расшифровывать данные.

--Создаём таблицу слов
CREATE TABLE MyWords(Val nvarchar(max), EncryptVal nvarchar(max))
--и наполним её данными
INSERT INTO MyWords
SELECT 'Knyazev Alexey', null
UNION ALL
SELECT 'http://www.t-sql.ru', null
UNION ALL
SELECT 'SQL Server', null

--теперь зашифруем с помощью открытого ключа
DECLARE @k nvarchar(max), @k2 nvarchar(max)
SELECT @k=convert(nvarchar(max), justPublicKey) FROM MyKeys WHERE id=1

UPDATE MyWords
SET EncryptVal=dbo.EncryptString(Val, 512, @k)

Расшифровать можно так:

DECLARE @k nvarchar(max), @k2 nvarchar(max)
SELECT @k=convert(nvarchar(max), PublicAndPrivateKeys) FROM MyKeys WHERE id=1

SELECT *, dbo.DecryptString(EncryptVal, 512, @k) FROM MyWords

Вот и весь "велосипед", цель данного примера показать, в очередной раз, как CLR-сборки могут разнообразить и улучшить работу с SQL Server.

Tags: , , , , , ,

SQL Server

Читаем почту (IMAP). CLR-сборка.

by Alexey Knyazev 4. февраля 2010 08:22

В одной из предыдущих статей я писал, как читать почту в SQL Server 2005/2008/2008R2 по протоколу POP3 (http://www.t-sql.ru/post/POP3CLR.aspx), там же пообещал, что в ближайшее время покажу, как осуществлять доступ к почте по протоколу IMAP.

Область применения протокола IMAP ( Internet Message Access Protocol ) аналогична области применения протокола POP3: он тоже предназначен для получения почты и используется на участке между MUA получателя и хранилищем сообщений. IMAP предоставляет более широкие возможности работы с почтовыми ящиками, чем POP3: он позволяет работать с несколькими почтовыми ящиками на одном или нескольких серверах IMAP как с файлами и каталогами на собственной машине пользователя. Обычно почтовые ящики сервера IMAP действительно представляют собой файлы в специальном каталоге сервера и его подкаталогах.

Как и в прошлый раз - это будит CLR-сборка (работает достаточно шустро). Но прежде рекомендую ознакомиться с описанием IMAP-протокола.

Полный перечень всех команд, а так же описание протокола можно прочитать в Запросе комментариев (англ. Request for Comments, RFC) — документ из серии пронумерованных информационных документов Интернета, содержащих технические спецификации и Стандарты.

RFC 3501 (IMAP версии 4 издание 1 (IMAP4rev1)), он заменил RFC 2060 (IMAP версии 4 (IMAP4)). Русскую версию спецификации так же легко найти в РУ-нете (http://opds.sut.ru/electronic_manuals/mail/5_IMAP.htm, http://book.itep.ru/4/44/imap4443.htm)

Сервер IMAP ожидает соединения от клиентов на порту TCP 143. После установления соединения сервер посылает свое приветствие клиенту, и начинается диалог, в котором клиент посылает серверу команды, а сервер сообщает о результатах их выполнения или присылает затребованную клиентом информацию. Как и сеанс POP3, сеанс IMAP делится на несколько состояний ( states ). Допустимый набор команд зависит от текущего состояния сеанса. Сеанс может находиться в одном из следующих состояний:

  • -неаутентифицированное состояние (Not Authenticated State): клиент должен пройти процедуру аутентификации прежде, чем сможет выполнять большинство команд;
  • -аутентифицированное состояние (Authenticated State): клиент аутентифицирован и должен выбрать почтовый ящик, прежде чем сможет работать с отдельными сообщениями;
  • -выбранное состояние (Selected State): почтовый ящик выбран;
  • -состояние выхода (Logout State): сеанс завершается.

 

 

Переходы, обозначенные цифрами:

  1. соединение без предварительной аутентификации;
  2. соединение с предварительной аутентификацией;
  3. отвергнутое соединение;
  4. успешная аутентификация;
  5. успешное выполнение команды SELECT или EXAMINE;
  6. команда CLOSE или неудачное завершение команды SELECT или EXAMINE;
  7. команда LOGOUT или потеря связи.

Сами Команды клиента и ответы сервера IMAP я в этой статье описывать не буду, так как вы сами при желании сможете с ними ознакомиться по ссылкам выше, а сразу приведу код сборки:

using System;
using Microsoft.SqlServer.Server;
using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;

public class IMAPClr
{
    private static TcpClient IMAP;
    private static NetworkStream ns;
    private static StreamWriter sw;
    private static StreamReader sr;

    [SqlFunction]  

//Выводим кол-во писем
    public static int MailCount(string Host, string User, string Password)
    {

        string s = Connect(Host, 143);
        if (s.Substring(0, 4) != "* OK")
        {
            return -1;
        }

        s = Authenticate(User, Password);
        if (s.Substring(0, 4) != "$ OK")
        {
            return -2;
        }

        sw.WriteLine("$ LOGIN " + User + " " + Password);
        sw.Flush();
        Response();

        sw.WriteLine("$ STATUS INBOX (messages)");
        sw.Flush();

        string res = Response();
        Match m = Regex.Match(res, "[0-9]*[0-9]");

        Disconnect();
        return Convert.ToInt32(m.ToString());

    }

//Кол-во непрочитанных писем
    public static int MailUnreadCount(string Host, string User, string Password)
    {

        string s = Connect(Host, 143);
        if (s.Substring(0, 4) != "* OK")
        {
            return -1;
        }

        s = Authenticate(User, Password);
        if (s.Substring(0, 4) != "$ OK")
        {
            return -2;
        }

        sw.WriteLine("$ LOGIN " + User + " " + Password);
        sw.Flush();
        Response();

        sw.WriteLine("$ STATUS INBOX (unseen)");
        sw.Flush();

        string res = Response();
        Match m = Regex.Match(res, "[0-9]*[0-9]");

        Disconnect();
        return Convert.ToInt32(m.ToString());

    }

    [SqlFunction(FillRowMethodName = "FillRowHeaders"
    , TableDefinition = "MessageID int, MessageHeader nvarchar(max)")]

//Заголовки
    public static IEnumerable GetMessagesHeaders(string Host, string User, string Password, int MessageStart, int MessageEnd)
    {
        ArrayList rows = new ArrayList();

        string s = Connect(Host, 143);
        if (s.Substring(0, 4) != "* OK")
        {
            rows.Add(new object[] { -1, s });
            return rows;
        }

        s = Authenticate(User, Password);
        if (s.Substring(0, 4) != "$ OK")
        {
            rows.Add(new object[] { -2, s });
            return rows;
        }

        SelectInbox();

        while (MessageStart <= MessageEnd)
        {
            rows.Add(new object[] { MessageStart, GetMessageHeaders(MessageStart).ToString() });
            MessageStart += 1;
        }
        Disconnect();
        return rows;
    }

    public static void FillRowHeaders(Object row, out int MessageID, out string MessageHeader)
    {

        object[] xrow = (object[])row;
        MessageID = (int)xrow[0];
        MessageHeader = (string)xrow[1];

    }

    [SqlFunction(FillRowMethodName = "FillRowMessages"
    , TableDefinition = "MessageID int, Message nvarchar(max)")]

//Тело письма
    public static IEnumerable GetMessages(string Host, string User, string Password, int MessageStart, int MessageEnd)
    {
        ArrayList rows = new ArrayList();

        while (MessageStart <= MessageEnd)
        {
            string s = Connect(Host, 143);
            if (s.Substring(0, 4) != "* OK")
            {
                rows.Add(new object[] { -1, s });
                return rows;
            }

            s = Authenticate(User, Password);
            if (s.Substring(0, 4) != "$ OK")
            {
                rows.Add(new object[] { -2, s });
                return rows;
            }
            SelectInbox();
            rows.Add(new object[] { MessageStart, GetMessage(MessageStart).ToString()});
            Disconnect();
            MessageStart += 1;
        }

        return rows;
    }

    public static void FillRowMessages(Object row, out int MessageID, out string Message)
    {

        object[] xrow = (object[])row;
        MessageID = (int)xrow[0];
        Message = (string)xrow[1];
    }

//Подключение к IMAP-серверу
    private static string Connect(string Host, int port)
    {
        try
        {
            IMAP = new TcpClient(Host, port);
            ns = IMAP.GetStream();
            sw = new StreamWriter(ns);
            sr = new StreamReader(ns);
            return Response();
        }
        catch (SocketException ex)
        {
            return ex.Message;
        }
    }

//Отключаемся от сервера
    public static void Disconnect()
    {
        sw.WriteLine("$ LOGOUT");
        sw.Flush();
        IMAP.Close();
    }

//Идентификация пользователя
    public static string Authenticate(string User, string Password)
    {
        sw.WriteLine("$ LOGIN " + User + " " + Password);
        sw.Flush();
        return Response();
    }

//Открываем доступ к указанному почтовому ящику
    public static string SelectInbox()
    {
        sw.WriteLine("$ EXAMINE INBOX");
        sw.Flush();
        return Response();
    }

//Заголовок письма по его номеру
    public static object GetMessageHeaders(int index)
    {
        sw.WriteLine("$ FETCH " + index + " (body[header.fields (from subject date)])");
        sw.Flush();

        return Response();
    }

//Письмо по номеру
    public static object GetMessage(int index)
    {

        sw.WriteLine("$ FETCH " + index + " body[text]");
        sw.Flush();

        return Response();
    }

    private static string Response()
    {
        byte[] data = new byte[IMAP.ReceiveBufferSize];
        int ret = ns.Read(data, 0, data.Length);
        return Encoding.ASCII.GetString(data).TrimEnd();
    }

}

Если у Вас возникнут вопросы по коду, то буду рад ответить в комментариях к этой статье.

Далее регистрируем сборку и создаём набор T-SQL функций для работы с ней:

--Регистрируем сборку
CREATE ASSEMBLY ClrIMAP
FROM 'C:\IMAP\IMAPClr.dll'
WITH PERMISSION_SET = UNSAFE;
GO

--Функция выводит кол-во писем в ящике
CREATE FUNCTION [dbo].[MailCount]
(
@Host nvarchar(255),
@User nvarchar(255),
@Password nvarchar(255)
)
RETURNS [int] WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [ClrIMAP].[IMAPClr].[MailCount]
GO

--Функция с кол-ом непрочитанных писем
CREATE FUNCTION [dbo].[MailUnreadCount]
(
@Host nvarchar(255),
@User nvarchar(255),
@Password nvarchar(255)
)
RETURNS [int] WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [ClrIMAP].[IMAPClr].[MailUnreadCount]
GO

--Функция чтения заголовков писем
CREATE FUNCTION [dbo].[GetMessagesHeaders]
(
@Host nvarchar(255),
@User nvarchar(255),
@Password nvarchar(255),
@MessageStart int,
@MessageEnd int
)
RETURNS TABLE
(
MessageID INT,
MessageHeader NVARCHAR(max)
)
EXTERNAL NAME [ClrIMAP].[IMAPClr].[GetMessagesHeaders];
GO

--Функция чтения самого письма (писем)
CREATE FUNCTION [dbo].[GetMessages]
(
@Host nvarchar(255),
@User nvarchar(255),
@Password nvarchar(255),
@MessageStart int,
@MessageEnd int
)
RETURNS TABLE
(
MessageID INT,
Message NVARCHAR(max)
)
EXTERNAL NAME [ClrIMAP].[IMAPClr].[GetMessages];
GO

Пара примеров работы с этими функциями:

--Выводим кол-во писем на сервере (всего и новых)
select
[dbo].[MailCount] ('imap.MailServer.ru', 'MyMail@MailServer.ru', 'MyPassword') as MailCount,
[dbo].[MailUnreadCount] ('imap.MailServer.ru', 'MyMail@MailServer.ru', 'MyPassword') as MailUnreadCount

--Выводим 5 первых писем и их заголовки (от кого, дата, тема)
select t1.MessageID, t1.MessageHeader, t2.Message from
[dbo].[GetMessagesHeaders] ('imap.MailServer.ru', 'MyMail@MailServer.ru', 'MyPassword', 1, 5) t1
inner join
[dbo].[GetMessages] ('imap.MailServer.ru', 'MyMail@MailServer.ru', 'MyPassword', 1, 5) t2
on t1.MessageID=t2.MessageID

Пример результата:

 

Tags: , , , , , ,

SQL Server

Скрипт выгрузки данных в Inserts-файл

by Alexey Knyazev 25. января 2010 21:19

В одной из своих заметок в блоге я публиковал, как можно с помощью PowerShell заскриптовать все объекты той или иной БД на сервере баз данных (Скриптуем объекты БД (PoSh) ), а на днях в коментариях в этому скрипту появился вопрос, как заскриптовать сами данные, а не только "скелет" базы.

Но прежде чем показать скрипт на PowerShell, перечислю другие возможные способы реализации данной задачи

Во первых - подумайте, действительно ли вам необходимы данные в виде файла, не проще ли (а самое главное правильнее) сделать Бэкап базы

Второй вариант - это T-SQL скрипт, т.к. в сети легко найти подобное решение, то я не стал изобретать велосипед, а предлагаю воспользоваться скриптом Narayana Vyas Kondreddi: SQL Server 2000 либо SQL Server 2005/2008

Ещё одно решение - стандартный клиент для работы с SQL Server 2005 и выше: SSMS (Microsoft SQL Server Management Studio). Для SSMS2005 - это надстройка (ADD-IN) Generate Insert statements from resultsets, tables or database из пакета дополнительных надстроек http://www.ssmstoolspack.com/

При этом в SSMS2008 подобная надстройка добавлена: Tasks->Generate Scripts..., а дальше в Wizard`e отметить, что в скрипт мы хотим включить не только объекты БД, но и данные.

Ну и вариант на PowerShell с использованием SMO:

$server=Read-Host "Укажите имя сервера БД"
$database=Read-Host "Имя БД"
$output_file=Read-Host "Вывести результат в файл (укажите имя файла)"

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null

$srv = New-Object "Microsoft.SqlServer.Management.SMO.Server" $server
$db = New-Object ("Microsoft.SqlServer.Management.SMO.Database")
$tbl = New-Object ("Microsoft.SqlServer.Management.SMO.Table")
$scripter = New-Object ("Microsoft.SqlServer.Management.SMO.Scripter") ($server)

$db = $srv.Databases[$database]

$scripter.Options.ScriptSchema = $true;
$scripter.Options.ScriptData = $true;
$scripter.Options.DriAll = $true
$scripter.Options.DriAllConstraints = $true
$scripter.Options.DriAllKeys = $true
$scripter.Options.DriChecks = $true
$scripter.Options.DriClustered = $true
$scripter.Options.DriDefaults = $true
$scripter.Options.DriForeignKeys = $true
$scripter.Options.DriIncludeSystemNames = $true
$scripter.Options.DriIndexes = $true
$scripter.Options.DriNonClustered = $true
$scripter.Options.DriPrimaryKey = $true
$scripter.Options.DriUniqueKeys = $true

$scripter.Options.AppendToFile =$true

$scripter.Options.FileName = $output_file
$scripter.Options.ToFileOnly = $true

foreach ($tbl in $db.Tables)
{
foreach ($s in $scripter.EnumScript($tbl.Urn)) { write-host $s }
}

Список пар-ов ScriptingOptions, можно посмотреть на MSDN http://msdn.microsoft.com/ru-ru/library/microsoft.sqlserver.management.smo.scriptingoptions_members.aspx

Tags: , , , , ,

PowerShell | SQL Server

Powered by BlogEngine.NET 1.6.0.0
Все права защищены © T-SQL.RU | Alexey Knyazev 2008-2010

MVP:SQL