Работа с SQL Server в C# с помощью скриптинга. Часть 1
В этой статье я покажу вам, как работать с Microsoft SQL Server в C# проектах посредством скриптинга. Реализовать это можно как в Windows, так и в macOS. Поскольку Windows, очевидно, является намного более популярной целевой платформой для C# и SQL Server, больше внимания я уделю настройке под macOS. В конце концов, код для этих платформ будет одним и тем же.
Доступ к инстансу SQL Server с помощью скриптинга на самом деле дает множество преимуществ. Вот только несколько, из преимуществ, которые вы получите, настроив среду для выполнения скриптов:
- Доступ к SQL Server с помощью скриптинга предполагает гораздо меньше кода. Большую часть функций можно факторизировать. Один оператор на скриптовом языке может выполнять под капотом множество C# операторов — язык скриптинга по сути выполняет роль функционального языка.
- Любой SQL-оператор, который вы можете использовать напрямую с SQL Server, также может быть использован и в скриптах. Основным преимуществом здесь является то, что, если в ваш проект интегрирован Scripting Engine (обработчик скриптов), то вы можете запускать любой оператор SQL Server во время выполнения.
- Синтаксис скриптового языка может быть не только лаконичнее, проще и точнее, но он также полностью зависит от того, как вы сами решили определить этот синтаксис. Это преимущество раскрывается в полной мере, если вы используете скриптовый язык с открытым исходным кодом.
Простота не предшествует сложности, а вытекает из нее. – Алан Перлис (Alan Perlis)
Но я сразу хочу отметить, что существует один существенный недостаток, связанный с использованием скриптов, а именно накладные расходы на парсинг выражений. В этой статье я продемонстрирую вам, как уменьшить эти накладные расходы, используя в качестве примера вставку нескольких строк в базу данных.
В качестве языка скриптинга я буду использовать CSCS (Customized Scripting для C#). Я уже рассказывал об этом языке в нескольких мои предыдущих статьях для CODE Magazine (вы можете найти ссылки на них в конце этой статьи). CSCS — это скриптовый язык с открытым исходным кодом, который очень легко интегрировать в ваш C# проект. Открытый исходный код дает вам оговоренное выше преимущество в виде возможности модифицирования его в процессе разработки.
Среди прочего, я собираюсь раскрыть в этой статье следующие темы:
- Работа с SQL Server в macOS, где будут выполняться все примеры, приведенные в этой статье (код CSCS идентичен в macOS и в Windows).
- Как избежать SQL-инъекций в CSCS.
- Я продемонстрирую вам на примере, как можно использовать простые функциональные возможности курсора SQL Server в CSCS. Он допускает более интуитивно понятный синтаксис, чем при непосредственном использовании C#.
- Как вызывать хранимые процедуры SQL Server из CSCS и как использовать пользовательские типы данных SQL.
Установка Microsoft SQL Server в macOS
Поскольку установка и запуск SQL Server в Windows является вполне рутинной задачей, здесь вы увидите, как установить и запустить его в macOS. Чтобы запустить SQL Server на Mac, вам придется выполнить следующие шаги:
- Установите Docker для Mac (отсюда)
- Запустите только что установленное приложение Docker Desktop (оно должно быть доступно в папке “Applications”). Обычно оно расположено по следующему пути: /usr/local/bin/docker.
- Загрузите и установите SQL Server для Docker-образа Linux. Для запуска из вашего shell используйте следующую команду:
Если это не сработает из-за проблем с разрешениями, попробуйте запустить ту же команду с sudo (для этого вам нужно будет знать пароль администратора):
- Затем запустите только что установленный Docker-образ следующим образом:
docker run -d --name sql_server_demo -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=mySronggPwd123' -p 1433:1433 mcr.microsoft.com/mssql/server:2019-latest
- Вы также можете установить консольный клиент SQL Server, запустив в своем shell следующую команду:
npm install -g sql-cli
Если вы снова столкнетесь с какими-либо проблемами с разрешениями, то добавьте к команде выше sudo. Этот шаг не является обязательным, но настоятельно рекомендуется. Установите Microsoft Azure Data Studio, перейдя по ссылке.
Очевидно, что существует множество других бесплатных GUI-оболочек SQL Server, но я пришел к выводу, что Azure Data Studio для macOS достаточно мощная и составляет достойную конкуренцию Microsoft SQL Server Management Studio для Windows.
- Теперь вам осталось только проверить, что все работает так, как надо. Чтобы подключиться к вашему серверу из командной строки, используйте эту команду:
mssql -u sa -p myStronggPwd123
Чтобы проверить установленную версию Microsoft SQL Server, просто запустите:
SELECT @@version
Результат выполнения этой команды в моей системе продемонстрирован на рисунке 1.
В качестве альтернативы, вы можете проверить подключение, используя Azure Data Studio, кликнув на “New Connection”, а затем следуя указаниям мастера подключения, как показано на рисунке 2. Введите тот же пароль, который вы использовали при создании Docker-образа Microsoft SQL Server выше на шаге 4.

Настройка скриптинговой среды CSCS в C# проекте
Чтобы настроить CSCS-скриптинг в вашем проекте, для начала вам нужно будет загрузить его исходный код с https://github.com/vassilych/cscs и включить его в свой проект. Это типичный проект, который будет работать со всеми консольными или фоновыми проектами (как в Windows, так и в macOS).
Одним из способов включения CSCS Scripting Engine в Windows GUI проект является WPF (Windows Presentation Foundation) проект, доступный здесь. Еще один способ — мобильный проект Xamarin iOS / Android, который можно скачать отсюда. В конце этой статьи вы можете найти ссылки, которые описывают, как использовать оба этих проекта.
После того, как вы все настроите, проект Xamarin должен выглядеть как показано на рисунке 3. Исходный код Scripting Engine находится в разделе scripting.Shared. В случае с WPF-проектом скрипты будут находиться в разделе CSCS.

Точка входа CSCS Scripting Engine зависит от контекста проекта. Для простого консольного проекта точкой входа является статический метод файла Main.cs Main.ProcessScript(string script, string filename = «») . Для WPF-проекта точкой входа является статический метод CSCS_GUI.RunScript(string filename) в файле CSCS_GUI.cs. А для Xamarin проектов iOS и Android точкой входа служит статический метод CustomInit.InitAndRunScript(string fileName = «start.cscs») файла CustomInit.cs . Если вы решите использовать примеры проектов из упомянутых выше GitHub-репозиториев, методы, которые запускают CSCS Scripting Engine, будут запускаться автоматически на старте проекта.
Я также рекомендую установить CSCS Debugger и REPL-расширение для Visual Studio Code. Он позволяет запускать любой CSCS-скрипт во время выполнения (смотрите ссылки для скачивания и использования в конце статьи). Чтобы иметь возможность подключиться к вашему CSCS-проекту из Visual Studio Code, в стартовый CSCS-скрипт должна быть включена следующая строка (по умолчанию это будет start.cscs):
StartDebugger();
Создание базы данных и таблиц в SQL Server
После установки SQL Server и интеграции CSCS Scripting Engine в ваш проект вы можете приступать к созданию базы данных SQL Server, которую мы будем использовать в последующих примерах.
Это можно сделать в самом CSCS. Все функции SQL Server описаны в таблице 1. Сначала вам нужно создать новую базу данных:
SQLConnectionString("Data Source=localhost,1433; Initial Catalog=master;Database=master; User >Первый оператор инициализирует строку подключения к SQL Server (с базой данных master), а второй — создает новую базу данных. Также, так как вы можете запустить любой SQL-оператор с помощью функции SQLNonQuery() , в вашем арсенале есть еще один простой способ создания базы данных:
SQLNonQuery("CREATE DATABASE CSCS");
Далее вам нужно создать таблицу с пользователями. Обратите внимание, что в строке подключения к SQL Server вам теперь нужно указать новую базу данных CSCS, чтобы новая таблица была создана там:
SQLConnectionString( "Data Source=localhost,1433; Initial Catalog=CSCS;Database=CSCS; User Password=myStronggPwd123"); SQLNonQuery("CREATE TABLE Users ( ID int NOT NULL IDENTITY PRIMARY KEY, FirstName varchar(255), LastName varchar(255), Email varchar(255), Salary real, Timestamp datetime not null default current_timestamp)");
Обратите внимание на то, как мы создали таблицу Users: нет необходимости указывать ID пользователя и таймстемп: первому будет присвоено следующее по порядку целое число, а в качестве второго будет использоваться текущий таймстемп.
Давайте заполним только что созданную таблицу Users некоторыми тестовыми данными:
columns = "FirstName,LastName,Email,Salary"; SQLInsert("Users", columns, ["John", "Johnson", "john@gmail.com", 45000]); SQLInsert("Users", columns, ["Juan", "Perez", "juan@gmail.mx", 75000]); SQLInsert("Users", columns, ["Johannes", "Dei", "dei@my.ch", 65000]); SQLInsert("Users", columns, ["Jean", "Cap", "jean@my.fr", 49000]); SQLInsert("Users", columns, ["Giovanni", "Vasco", "gv@my.it", 34000]); SQLInsert("Users", columns, ["Joan", "Lee", "joan@my.es", 74000]);
После что таблица будет выглядеть, как показано на рисунке 4:

Список реализованных в настоящее время CSCS-функций, связанных с SQL Server, вы можете найти в таблице 1.
Теперь мы можем начать нашу работу с SQL через CSCS-скриптинг.
Базовые функции SQL Server
Самый простой способ использовать скрипты во время выполнения после запуска основной программы — использовать REPL-расширение CSCS для Visual Studio Code. С ним вы сможете запустить новый скрипт после запуска программы. Этот REPL-функционал можно использовать следующим образом: выберите код, который вы хотите запустить, а затем нажмите Ctrl + 8 в Windows или Command + 8 в macOS.
На рисунке 5 показано, как можно запросить информацию о столбцах созданной вами таблицы Users.

Команда SQLTableColumn(tableName) возвращает список имен столбцов вместе с их типами. Если вам нужны только имена столбцов, укажите второй аргумент (“onlyNames” должен иметь значение true). Подробности смотрите в таблице 1.
Функция SQLQuery() используется для запуска Select -операторов и получения списка результатов. Рассмотрим следующий оператор SQLQuery() :
results = SQLQuery("SELECT FirstName,Salary FROM Users WHERE Salary > 50000 ORDER BY Salary");
В результате выполнения этого оператора переменной будет присвоен список, содержащий четыре элемента:
[[FirstName, Salary], [Johannes, 65000], [Joan, 74000] [Juan, 75000]]
Каждый элемент в возвращенном списке также является списком, которых содержит два элемента для каждого из столбцов в операторе Select. Первый элемент возвращаемого списка всегда содержит имена столбцов, а остальные содержат сами строки. Таким образом, возвращаемый список по факту представляет из себя двумерный массив: results[0][0] = «FirstName», results[1][1] = 65000 и т. д.
Функция SQLNonQuery() позволяет выполнять все остальные операторы SQL Server. Она может обновлять таблицы, удалять строки, создавать новые таблицы или хранимые процедуры и т. д. Эта функция возвращает количество затронутых строк в случае операторов UPDATE, DELETE или INSERT. В остальных случаях она всегда возвращает -1.
Вот один из примеров использования этой функции:
updated = SQLNonQuery("UPDATE Users SET Salary = 48500 WHERE // returns 1
После выполнения приведенного выше оператора переменная updated будет равна 1 (затронута всего одна строка). Ниже вас ждет еще пара примеров использования функции SQLNonQuery() .
Скриптинг и SQL-инъекции
Любой из приведенные выше примеров может быть потенциально использован для SQL-инъекций, если одно из полей, используемых в SQL-запросе или в любом другом операторе, имеет значение, которое должен предоставить пользователь.
SQL-инъекция — это атака с внедрением кода, в рамках которой злоумышленники имеют возможность выполнять вредоносные SQL-операторы, чтобы либо повредить сервер, либо извлечь данные, к которым у них не должно быть доступа.
Например, с помощью атаки с внедрением кода через поле для ввода данных вы можете получить адрес электронной почты пользователя, а затем извлечь информацию о пользователе следующим образом:
SQLQuery("SELECT * FROM Users WHERE Email='" + email + "'");
Затем злоумышленник может ввести этот текст вместо электронной почты:
"x@x.com' or 1=1 --";
Далее этот аргумент может попасть в SQLQuery, что будет выглядеть следующим образом:
SQLQuery("SELECT * FROM Users WHERE Email='x@x.com' or 1=1 --'");
Этот запрос возвращает всех пользователей, поскольку условие 1=1 всегда истина! Чтобы избежать такого рода хакерских атак, можно использовать следующие средства защиты:
- Используйте хранимые процедуры (им посвящен следующий раздел).
- Используйте параметризованные параметры (это мы тоже разберем чуть дальше).
Чтобы исправить приведенный выше Select-оператор, можно использовать параметризованный вызов, в котором вы дополнительно предоставляете список параметров для запроса. Этот список в свою очередь будет состоять из списков из двух элементов, где первый элемент — имя параметризованного параметра (такое же, как используется в запросе), а второй элемент — фактическое значение. Вот так будет выглядеть “безопасный” вызов SQL-запроса:
email = "juan@gmail.mx"; SQLQuery("SELECT * FROM Users WHERE Email=@0", [["@0", email]]);
Точно так же вы можете использовать параметры с любыми другими операторами SQL Server. Вот как будет выглядеть параметризованный вызов оператора Update из предыдущего раздела, только с двумя параметрами:
updated = SQLNonQuery("UPDATE Users SET Salary = @0 WHERE [["@0", 48500], ["@1", 4]]);
Также, если вы используете хранимые процедуры, вы можете безопасно передавать им аргументы. Об этом мы поговорим во второй части, которая выйдет буквально через несколько дней.
А пока приглашаем всех желающих на открытое занятие, на котором поговорим о модульном тестировании кода SQL Server и использовании для этого tSqlt. Занятие состоится уже сегодня вечером, записаться можно по ссылке.
Также приходите на бесплатный урок «Статический анализатор кода на Roslyn своими руками». На этом занятии разберем по шагам создание собственного статического анализатора кода на базе Roslyn API. Регистрация доступна на странице курса «C# Developer. Professional».
- Блог компании OTUS
- Microsoft SQL Server
- C#
Выполнение SQL-скриптов
При написании интеграционных тестов для реляционной базы данных зачастую полезно выполнять SQL-скрипты для изменения схемы базы данных или вставки тестовых данных в таблицы. Модуль spring-jdbc обеспечивает поддержку инициализации встроенной или существующей базы данных путем выполнения SQL-скриптов при загрузке ApplicationContext в Spring. Подробнее см. в разделах «Поддержка встроенных баз данных» и «Тестирование логики доступа к данным с использованием встроенной базы данных».
Хотя и очень разумно инициализировать базу данных для тестирования единожды при загрузке ApplicationContext , иногда всё же необходимо иметь возможность изменять базу данных во время интеграционных тестов. В следующих разделах объясняется, как запускать SQL-скрипты программно и декларативно во время интеграционных тестов.
Программное выполнение SQL-скриптов
Spring предоставляет следующие средства для выполнения SQL-скриптов программно в методах интеграционного тестирования.
- org.springframework.jdbc.datasource.init.ScriptUtils
- org.springframework.jdbc.datasource.init.ResourceDatabasePopulator
- org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests
- org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests
ScriptUtils предоставляет коллекцию статических методов для работы с SQL-скриптами и в основном предназначен для внутреннего использования в рамках фреймворка. Однако если необходим полный контроль над анализом и выполнением SQL-скриптов, ScriptUtils может подходить лучше, чем некоторые иные альтернативы, описанные далее. Более подробную информацию смотрите в javadoc по отдельным методам в ScriptUtils .
ResourceDatabasePopulator предоставляет объектно-ориентированный API-интерфейс для программного заполнения, инициализации или очистки базы данных с помощью SQL-скриптов, определенных во внешних ресурсах. ResourceDatabasePopulator предоставляет опции для конфигурирования кодировки символов, разделителя инструкций, разграничителей комментариев и флагов обработки ошибок, используемых при синтаксическом анализе и выполнении скриптов. Каждый из параметров конфигурации имеет значение по умолчанию. Подробности о значениях по умолчанию см. в javadoc. Для выполнения скриптов, сконфигурированных в ResourceDatabasePopulator , можно вызвать либо метод populate(Connection) , чтобы выполнить модуль заполнения в отношении java.sql.Connection , либо метод execute(DataSource) , чтобы выполнить модуль заполнения в отношении javax.sql.DataSource . В следующем примере заданы SQL-скрипты для тестовой схемы и тестовых данных, разделитель инструкций установлен в значение @@ , а скрипты запускаются в отношении DataSource :
@Test void databaseTest() < ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); populator.addScripts( new ClassPathResource("test-schema.sql"), new ClassPathResource("test-data.sql")); populator.setSeparator("@@"); populator.execute(this.dataSource); // запускаем код, использующий тестовую схему и данные >
@Test fun databaseTest() < val populator = ResourceDatabasePopulator() populator.addScripts( ClassPathResource("test-schema.sql"), ClassPathResource("test-data.sql")) populator.setSeparator("@@") populator.execute(dataSource) // запускаем код, использующий тестовую схему и данные >
Обратите внимание, что ResourceDatabasePopulator внутренне делегирует ScriptUtils полномочия для синтаксического анализа и выполнения SQL-скриптов. Точно так же методы executeSqlScript(..) в AbstractTransactionalJUnit4SpringContextTests и AbstractTransactionalTestNGSpringContextTests внутренне используют ResourceDatabasePopulator , чтобы выполнить SQL-скрипты. Более подробную информацию смотрите в Javadoc по различным методам executeSqlScript(..) .
Декларативное выполнение SQL-скриптов с помощью аннотации @Sql
В дополнение к вышеупомянутым механизмам для выполнения SQL-скриптов программно, можно декларативно конфигурировать SQL-скрипты в Spring TestContext Framework. В частности, можно объявить аннотацию @Sql для тестового класса или тестового метода, чтобы сконфигурировать отдельные SQL-инструкции или пути к ресурсам SQL-скриптов, которые должны быть выполнены в отношении заданной базы данных перед или после метода интеграционного тестирования. Поддержка аннотации @Sql обеспечивается слушателем SqlScriptsTestExecutionListener , который активирован по умолчанию.
Объявления аннотации @Sql на уровне метода по умолчанию переопределяют объявления на уровне классов. Однако, начиная со Spring Framework 5.2, эту логику работы можно сконфигурировать для каждого тестового класса или каждого тестового метода через аннотацию @SqlMergeMode .
Семантика ресурса пути
Каждый путь интерпретируется как Resource из Spring. Простой путь (например, «schema.sql» ) считается ресурсом пути классов, который относиться к пакету, в котором определен тестовый класс. Путь, начинающийся с косой черты, считается абсолютным ресурсом пути классов (например, «/org/example/schema.sql» ). Путь, ссылающийся на URL-адрес (например, путь с префиксами classpath: , file: , http: ), загружается с использованием указанного протокола ресурса.
В следующем примере показано, как использовать аннотацию @Sql на уровне класса и на уровне метода в классе интеграционного теста на основе JUnit Jupiter:
@SpringJUnitConfig @Sql("/test-schema.sql") class DatabaseTests < @Test void emptySchemaTest() < // выполняем код, использующий тестовую схему без каких-либо тестовых данных >@Test @Sql() void userTest() < // выполняем код, использующий тестовую схему и тестовые данные >>
@SpringJUnitConfig @Sql("/test-schema.sql") class DatabaseTests < @Test fun emptySchemaTest() < // выполняем код, использующий тестовую схему без каких-либо тестовых данных >@Test @Sql("/test-schema.sql", "/test-user-data.sql") fun userTest() < // выполняем код, использующий тестовую схему и тестовые данные >>
Обнаружение скриптов по умолчанию
Если скрипты или инструкции SQL не заданы, предпринимается попытка определить default скрипт в зависимости от того, где объявлена аннотация @Sql . Если значение по умолчанию не может быть определено, будет сгенерировано исключение IllegalStateException .
- Объявление на уровне класса: Если аннотированный тестовый класс — com.example.MyTest , то соответствующий скрипт по умолчанию — classpath:com/example/MyTest.sql .
- Объявление на уровне метода: Если аннотированный тестовый метод имеет имя testMethod() и определен в классе com.example.MyTest , то соответствующий скрипт по умолчанию будет называться classpath:com/example/MyTest.testMethod.sql .
Объявление нескольких наборов аннотаций @Sql
Если нужно настроить несколько наборов SQL-скриптов для данного класса или метода тестирования, но с разной конфигурацией синтаксиса, разными правилами обработки ошибок или разными фазами выполнения для каждого набора, можно объявить несколько экземпляров аннотации @Sql . В Java 8 можно использовать аннотацию @Sql в качестве повторяющейся аннотации. Или же можно использовать аннотацию @SqlGroup как явный контейнер для объявления нескольких экземпляров аннотации @Sql .
В следующем примере показано, как использовать аннотацию @Sql в качестве повторяющейся аннотации в Java 8:
@Test @Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")) @Sql("/test-user-data.sql") void userTest() < // выполняем код, использующий тестовую схему и тестовые данные >
// Повторяющиеся аннотации с не-SOURCE сохранением пока еще не поддерживаются Kotlin
В сценарии, представленном в предыдущем примере, скрипт test-schema.sql использует иной синтаксис для однострочных комментариев.
Следующий пример идентичен предыдущему, за исключением того, что объявления аннотации @Sql сгруппированы вместе в аннотации @SqlGroup . В версии Java 8 и выше использование аннотации @SqlGroup необязательно, но аннотацию @SqlGroup может понадобиться использовать для совместимости с другими языками JVM, такими как Kotlin.
@Test @SqlGroup( < @Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")), @Sql("/test-user-data.sql") )>void userTest() < // выполняем код, использующий тестовую схему и тестовые данные >
@Test @SqlGroup( Sql("/test-schema.sql", config = SqlConfig(commentPrefix = "`")), Sql("/test-user-data.sql")) fun userTest() < // выполняем код, использующий тестовую схему и тестовые данные >
Фазы выполнения скриптов
По умолчанию SQL-скрипты выполняются перед соответствующим тестовым методом. Однако если нужно запустить определенный набор скриптов после тестового метода (например, для очистки состояния базы данных), можно использовать атрибут executionPhase в аннотации @Sql , как показано в следующем примере:
@Test @Sql( scripts = "create-test-data.sql", config = @SqlConfig(transactionMode = ISOLATED) ) @Sql( scripts = "delete-test-data.sql", config = @SqlConfig(transactionMode = ISOLATED), executionPhase = AFTER_TEST_METHOD ) void userTest() < // выполняем код, который предписывает фиксировать тестовые данные // в базе данных вне тестовой транзакции >
@Test @SqlGroup( Sql("create-test-data.sql", config = SqlConfig(transactionMode = ISOLATED)), Sql("delete-test-data.sql", config = SqlConfig(transactionMode = ISOLATED), executionPhase = AFTER_TEST_METHOD)) fun userTest() < // выполняем код, который предписывает фиксировать тестовые данные // в базе данных вне тестовой транзакции >
Обратите внимание, что ISOLATED и AFTER_TEST_METHOD статически импортированы из Sql.TransactionMode и Sql.ExecutionPhase , соответственно.
Конфигурирование скрипта с помощью @SqlConfig
Можно сконфигурировать синтаксический анализ скрипта и обработку ошибок с помощью аннотации @SqlConfig . Если @SqlConfig объявляется как аннотация на уровне класса для класса интеграционного теста, то она служит глобальной конфигурацией для всех SQL-скриптов в иерархии тестового класса. При прямом объявлении с помощью атрибута config аннотации @Sql , аннотация @SqlConfig служит локальной конфигурацией для SQL-скриптов, объявленных в аннотации @Sql . Каждый атрибут в аннотации @SqlConfig имеет неявное значение по умолчанию, которое документировано в javadoc соответствующего атрибута. Из-за правил, определенных для атрибутов аннотаций в спецификации языка Java ( Java Language Specification), к сожалению, невозможно присвоить атрибуту аннотации значение null . Таким образом, для поддержки переопределения унаследованной глобальной конфигурации атрибуты аннотации @SqlConfig имеют явное значение по умолчанию либо «» (для строк), <> (для массивов), либо DEFAULT (для перечислений). Этот подход позволяет локальным объявлениям аннотации @SqlConfig выборочно переопределять отдельные атрибуты из глобальных объявлений аннотации @SqlConfig , предоставляя значение, отличное от «» , <> или DEFAULT . Глобальные атрибуты аннотации @SqlConfig наследуются всегда, если локальные атрибуты аннотации @SqlConfig не предоставляют явного значения, отличного от «» , <> или DEFAULT . Поэтому явная локальная конфигурация имеет приоритет над глобальной конфигурацией.
Параметры конфигурации, предоставляемые аннотациями @Sql и @SqlConfig , эквивалентны тем, которые поддерживаются ScriptUtils и ResourceDatabasePopulator , но являются надмножеством тех, которые предоставляются элементом пространства имен XML . Подробности смотрите в javadoc по отдельным атрибутам в аннотациях @Sql и @SqlConfig .
Управление транзакциями для аннотации @Sql
По умолчанию SqlScriptsTestExecutionListener создает желаемую семантику транзакций для скриптов, сконфигурированных с помощью аннотации @Sql . В частности, SQL-скрипты выполняются без транзакции в рамках существующей транзакции, управляемой Spring (например, транзакции, управляемой TransactionalTestExecutionListener для теста, помеченного аннотацией @Transactional ) или в рамках изолированной транзакции, в зависимости от сконфигурированного значения атрибута transactionMode в аннотации @SqlConfig и наличия PlatformTransactionManager в ApplicationContext теста. Однако, как минимум, javax.sql.DataSource должен присутствовать в ApplicationContext теста.
Если алгоритмы, используемые SqlScriptsTestExecutionListener для определения DataSource и PlatformTransactionManager и вывода семантики транзакции не удовлетворяют вашим потребностям, то можно указать явные имена, установив атрибуты dataSource и transactionManager в аннотации @SqlConfig . Кроме того, можно управлять логикой распространения транзакций, задавая атрибут transactionMode в аннотации @SqlConfig (например, следует ли запускать скрипты в изолированной транзакции). Хотя подробное рассмотрение всех поддерживаемых вариантов управления транзакциями с помощью аннотации @Sql выходит за рамки данного справочного руководства, javadoc для аннотации @SqlConfig и слушателя SqlScriptsTestExecutionListener содержат подробную информацию, а в следующем примере показан типичный сценарий тестирования с использованием JUnit Jupiter и транзакционных тестов с аннотацией @Sql :
@SpringJUnitConfig(TestDatabaseConfig.class) @Transactional class TransactionalSqlScriptsTests < final JdbcTemplate jdbcTemplate; @Autowired TransactionalSqlScriptsTests(DataSource dataSource) < this.jdbcTemplate = new JdbcTemplate(dataSource); >@Test @Sql("/test-data.sql") void usersTest() < // проверяем состояние в тестовой базе данных: assertNumUsers(2); // выполняем код, использующий тестовые данные. >int countRowsInTable(String tableName) < return JdbcTestUtils.countRowsInTable(this.jdbcTemplate, tableName); >void assertNumUsers(int expected) < assertEquals(expected, countRowsInTable("user"), "Number of rows in the [user] table."); >>
@SpringJUnitConfig(TestDatabaseConfig::class) @Transactional class TransactionalSqlScriptsTests @Autowired constructor(dataSource: DataSource) < val jdbcTemplate: JdbcTemplate = JdbcTemplate(dataSource) @Test @Sql("/test-data.sql") fun usersTest() < // проверяем состояние в тестовой базе данных: assertNumUsers(2) // выполняем код, использующий тестовые данные. >fun countRowsInTable(tableName: String): Int < return JdbcTestUtils.countRowsInTable(jdbcTemplate, tableName) >fun assertNumUsers(expected: Int) < assertEquals(expected, countRowsInTable("user"), "Number of rows in the [user] table.") >>
Обратите внимание, что нет необходимости очищать базу данных после выполнения метода usersTest() , поскольку любые изменения, внесенные в базу данных (как в тестовом методе, так и в скрипте /test-data.sql ), автоматически откатываются TransactionalTestExecutionListener (см. подробнее в разделе, посвященном управлениию транзакциями ).
Объединение и переопределение конфигурации с помощью аннотации @SqlMergeMode
Начиная со Spring Framework 5.2, можно объединять объявления аннотации @Sql на уровне методов с объявлениями на уровне классов. Например, это позволит предоставлять конфигурацию для схемы базы данных или некоторые общие тестовые данные для тестового класса единожды, а затем предоставлять дополнительные, специфические для конкретного случая тестовые данные для каждого тестового метода. Чтобы активировать объединение аннотаций @Sql , аннотируйте ваш тестовый класс или тестовый метод с помощью аннотации @SqlMergeMode(MERGE) . Чтобы дезактивировать объединение для конкретного тестового метода (или конкретного тестового подкласса), можно переключиться обратно в режим по умолчанию с помощью аннотации @SqlMergeMode(OVERRIDE) . Обратитесь к разделу документации, посвященному аннотации @SqlMergeMode для ознакомления с примерами и получения более подробной информации.
Как открыть скрипт в sql
Плз помогите мне в этом, в общем-то, простом вопросе .
Все факи излазил, но так и не разобрался .
Ситуация такова: у меня на локальном mssql server есть достаточно большая база (таблиц 5 по 3000 записей). Нужно скопировать её на удалённый сервер. Встроенный средства вроде export/import или sql query analyzer совершенно не подходят, потому что на dial up это похоже на форменное извращение.
Я экспортировал базу в .sql-скрипты, закачал их на сервер. На сервере Enterprise Manager’а и Sql Query Analyzer’а нет. Нашёл и установил на сервер в общем-то неплохую прогу EMS MS SQL Manager, с её помощью импортировал все скрипты. но! одна существенная проблема — при импортировании слетел чарсет то есть, то, что у меня на сервере было кириллицей, на удалённом сервере получилось в виде western (то есть латинские буквы с крышками). Как решить это, не нашёл . Конкурирующих программ тоже не особо.
Уже несколько дней мучаюсь. помогите, плз.
Выполнение SQL-скрипта:
Создание базы данных в большей степени является функцией администрирования, в следствии чего создание БД не вошло в скрипт.
Выполнение SQL-скрипта в общем виде происходит следующим образом:
Средствами СУБД создается база данных, базе данных назначаются пользователи и производятся другие действия администрирования. После происходит подключение к созданной базе данных, средствами СУБД открывается и запускается созданный SQL-скрипт.
Запустить WEB-приложение «Get Started With Oracle Database 11g Express Edition «,выбрать ссылку «Application Express».

Авторизоваться администратором СУБД.

Ввести имя новой базы данных, имя пользователя для новой базы данных, пароль и повторение пароля. Нажать кнопку «Create Workspace».

Для входа в новую базу данных, и авторизации под новым пользователем нажмите «click here»

Введите пароль. Нажмите «Login».

Нажмите кнопку «SQL Workshop».

Нажмите кнопку «SQL Scripts».

Нажмите кнопку «Upload».

Кнопкой «обзор» необходимо выбрать созданный SQL-скрипт, введите название скрипта и в установках файла необходимо выбрать «Cyrilic Windows 1251» для корректного отображения русских символов. Нажмите «Upload».

Нажмите указанную кнопку в столбце «Run».

Нажмите кнопку «Run Now».

Корректность выполнения возможно проверить нажав на указанную кнопку в столбце «View Results».

— в СУБД PostgreSQL
Запустить pgAdmin III, подключиться к необходимому серверу. Находясь на узле «Базы данных» правой клавишей мыши вызвать контекстное меню и выбрать «Новая база данных».

В окне создания новой базы данных необходимо ввести имя новой базы данных и ее владельца и по окончанию нажать «Ок».

После чего в списках баз данных появится введенная база данных.

При использовании столбцов с типом geography. Необходимо базе данных подключить расширения postgis, postgis_topology.
В базе данных в узле «Расширения» правой клавишей мыши вызвать контекстное меню и выбрать «Новое расширение».

В окне создания нового расширения выбрать имя расширения postgis и по окончанию нажать «Ок».

Повторить вышеописанные действия для расширения postgis_topology.
Далее кнопкой указанной на рисунке вызвать редактор SQL-запросов.

Кнопкой «Открыть файл» или через главное меню Файл->Открыть открыть созданный SQL-скрипт

Далее кнопкой «Выполнить запрос» или через главное меню Запрос->Выполнить выпонить скрипт.

При корректности выполняемых действий редактор SQL-запросов сообщит об успешности выполненного скрипта.

Запустить «Среда SQL Server Management Studio», подключиться к необходимому серверу. Находясь на узле «Базы данных» правой клавишей мыши вызвать контекстное меню и выбрать «Создать базу данных».

В окне создания новой базы данных необходимо ввести имя новой базы данных и при необходимости ее владельца и по окончанию нажать «Ок».

Кнопкой «Открыть файл» или через главное меню Файл->Открыть ->Файл открыть созданный SQL-скрипт

Перед выполнением скрипта убедитесь, что скрипт будет выполнятся именно для вновь созданной базы данных.
Далее кнопкой «Выполнить запрос» или через главное меню Запрос->Выполнить выполнить скрипт.

При корректности выполняемых действий Management Studio сообщит об успешности выполненного скрипта.
