Microsoft SQL Server, PostgreSQL, Qt, Базы данных

Резервное копирование базы данных по расписанию: MS SQL Server и PostgreSQL

Резервное копирование базы данных по расписанию: MS SQL Server и PostgreSQLНе во всех СУБД есть возможность настроить Резервное копирование базы данных по расписанию штатными средствами. Например, в Microsoft SQL Server это делается без проблем, а вот в PostgreSQL такой возможности «из коробки» нет.

Но выход есть: создать файл сценария и добавить его исполнение в расписание задач в Windows.

В переменных database, host, port, userName, bin, backupDir будут храниться значения имени базы данных, сервера, порта, имени пользователя БД, путь к bin папке PostgreSQL и директории сохранения резервных копий соответственно.

Пусть значение driver = 0 будет отвечать за PostgreSQL, а 1 — за Microsoft SQL Server.

Определим текст *.bat-файла:

[pastacode lang=»cpp» manual=»QString%20batText%20%3D%20%22%40ECHO%20OFF%20%5Cn%22%0A%20%20%20%20%20%20%20%20%22SET%20dmpfile%3D%22%2Bdatabase%2B%22-FullBackup-%25DATE%3A~6%2C4%25-%25DATE%3A~3%2C2%25-%25DATE%3A~0%2C2%25%20%5Cn%22%0A%20%20%20%20%20%20%20%20%22IF%20%5C%22%25TIME%3A~0%2C1%25%5C%22%3D%3D%5C%22%20%5C%22%20(SET%20dmpfile%3D%25dmpfile%25-0%25TIME%3A~1%2C1%25)%20ELSE%20(SET%20dmpfile%3D%25dmpfile%25-%25TIME%3A~0%2C2%25)%20%5Cn%22%0A%20%20%20%20%20%20%20%20%22SET%20dmpfile%3D%25dmpfile%25-%25TIME%3A~3%2C2%25-%25TIME%3A~6%2C2%25.backup%20%5Cn%22%0A%20%20%20%20%20%20%20%20%22set%20text%20%3D%20Begin%20to%20backup…%20%5Cn%22%0A%20%20%20%20%20%20%20%20%22echo%20%25text%25%20%5Cn%22%3B%0Aif%20(driver%3D%3D0)%0A%20%20%20%20%20%20%20batText%20%2B%3D%20QString(%0A%20%20%20%20%20%20%20%20%20%20%20%22cd%20%251%5C%20%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%22pg_dump.exe%20—host%20%252%20—port%20%253%20—username%20%254%20—no-password%20—format%22%20%0A%09%09%20%20%20%22custom%20—blobs%20—verbose%20—file%20%5C%22%255%5C%5C%25dmpfile%25%5C%22%20%256%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20.arg(bin%2C%20host%2C%20port%2C%20userName%2C%20%0A%09%09%09%09%20backupDir.replace(%22%2F%22%2C%20%22%5C%5C%22)%2C%20database)%3B%0A%20else%0A%20%20%20%20%20%20%20batText%20%2B%3D%20QString(%22SQLCMD%20-S%20%251%20-E%20-Q%20%5C%22BACKUP%20DATABASE%20%252%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%22TO%20DISK%20%3D%20’%253%2F%25dmpfile%25’%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%22WITH%20INIT%2C%20NOFORMAT%2C%20SKIP%2C%20NOUNLOAD%5C%22%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.arg(host%2C%20database%2C%20backupDir)%3B» message=»» highlight=»» provider=»manual»/]

Имя файла резервной копии будет иметь при этом подобный вид: DatabaseName-FullBackup-2018-08-07 -11-23-38.backup, то есть имя базы данных, FullBackup + таймстемп.

Далее запишем текст в файл: Продолжить чтение «Резервное копирование базы данных по расписанию: MS SQL Server и PostgreSQL»

Microsoft SQL Server, PostgreSQL, Базы данных

Триггер на групповую вставку в таблицу в Microsoft SQL Server

Многие СУБД (например, MySQL, PostgreSQL и т.д.) умеют правильно обрабатывать события по групповой вставке данных в таблицы. Но не все. Например, триггер на групповую вставку в таблицу в Microsoft SQl Server будет отличаться. Рассмотрим примеры запросов:

[pastacode lang=»sql» manual=»insert%20into%20people%0Aselect%20name%2C%20surname%2C%20age%20from%20portfolio%3B» message=»» highlight=»» provider=»manual»/]

Или такой:

[pastacode lang=»sql» manual=»insert%20into%20people(name%2C%20surname%2C%20age)%20values%0A(‘John’%2C%20’Smith’%2C%2012)%2C%0A(‘Ann’%2C%20’Black’%2C%2029)%2C%0A(‘Samantha’%2C%20’Doeson’%2C%2038)%3B» message=»» highlight=»» provider=»manual»/]

Продолжить чтение «Триггер на групповую вставку в таблицу в Microsoft SQL Server»

Microsoft SQL Server, PostgreSQL

Функция, возвращающая таблицу returns table — в PostgreSQL и MS SQL Server

Хочу сегодня привести примеры создания функций для СУБД Microsoft SQL Server и PostgreSQL. Функция возвращает таблицу с 3-мя полями.

Как это пишется в MS SQL Server:

CREATE FUNCTION dbo.myFunction (--variables list--)
RETURNS result_table TABLE(field1 integer, field2 integer, field3 integer) 
AS
BEGIN
	insert into result_table 
	select val1, val2, val3 from another_table;
	return;
END;

А вот так в PostgreSQL:

CREATE OR REPLACE FUNCTION public.get_count_in_batch(--variables list--)
    RETURNS TABLE(field1 integer, field2 integer, field3 integer) 
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE 
    ROWS 1000
AS $BODY$
begin
	return query select val1, val2, val3 from another_table;
end;
$BODY$;

Конечно, здесь примеры сокращены до минимума, только лишь с целью показать механизм возврата результата. Продолжить чтение «Функция, возвращающая таблицу returns table — в PostgreSQL и MS SQL Server»

PostgreSQL, Базы данных

PostgreSQL: Узнать данные о колонках таблицы

Из таблицы information_schema.columns можно узнать много чего полезного о колонках той или иной таблицы или всех таблиц сразу. А также и представлений.

Узнаем все данные о колонках таблиц и представлений схемы ‘public’ базы данных ‘my_database’:

select * from information_schema.columns
where table_catalog = 'my_database' and table_schema = 'public'

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

Чтобы получить перечень колонок и присвоенные им номера по порядку таблицы products, надо написать

select column_name, ordinal_position
from information_schema.columns
where table_catalog = 'products' and 
table_schema = 'public' and 
table_name = 'products'
PostgreSQL, Базы данных

Insert … on conflict do update — Обновление записи при вставке, если возникает нарушение ограничения

Как без предварительной проверки существования записи по первичному ключу, сразу вставлять ее, а при возникновения конфликта — просто обновить? И все за раз. Необходимо воспользоваться предложением on conflict … do …

Подробней об этом расскажет страница документации.

Я покажу пример, как при возникновении нарушения уникальности первичного ключа обновить данные. Продолжить чтение «Insert … on conflict do update — Обновление записи при вставке, если возникает нарушение ограничения»

PostgreSQL, SQL, Базы данных

Вывод даты с указанием часового и минутного смещения timezone в PostgreSQL

Для выделения часового сдвига даты формата timestamp with time zone есть функция extract(timezone_hour from date_), где date_ — дата, откуда необходимо извлечь смещение. Чтобы узнать минутное смещение есть функция extract(timezone_minute from date_). Но они обе покажут значение длиной 1, если оно меньше 10. Например, 3 вместо 03.

Напишем функцию, которая преобразует переданное значение даты в формат записи 2018-04-04T14:10:29+03:00: Продолжить чтение «Вывод даты с указанием часового и минутного смещения timezone в PostgreSQL»

Базы данных

Триггеры в PostgreSQL

Захотелось посвятить одну запись триггерам. Люблю я их за то, что делают некоторую работу без моего участия, это так ценно 🙂

Как создать триггер?

Сначала напишем триггерную функцию, которая и будет выполнять некоторые действия при модификации той или иной таблицы. Продолжить чтение «Триггеры в PostgreSQL»

Qt, Базы данных

Qt. Динамическое создание виджетов на форме

Динамическое создание виджетов на форме может помочь, когда расположение и/или видимость виджетов подпадает под какие-то условия. Приведу пример. Допустим, в базе данных есть некая таблица, в которой хранятся настройки видимости, подписи, id наименований колонок основных таблиц базы, где хранятся важные данные:

[pastacode lang=»sql» manual=»CREATE%20TABLE%20table_settings%0A(%0Aid%20serial%20NOT%20NULL%2C%0Atable_id%20integer%20NOT%20NULL%2C%0Acolumn_id%20integer%2C%0Avisible%20boolean%20NOT%20NULL%20DEFAULT%20true%2C%0Acaption%20character%20varying(50)%2C%0Aname_%20character%20varying(50)%2C%0ACONSTRAINT%20table_settings_pkey%20PRIMARY%20KEY%20(id)%2C%0ACONSTRAINT%20table_settings_table_id_fkey%20FOREIGN%20KEY%20(table_id)%0AREFERENCES%20table_names%20(id)%20MATCH%20SIMPLE%0AON%20UPDATE%20CASCADE%20ON%20DELETE%20CASCADE%0A)» message=»» highlight=»» provider=»manual»/]

где

  • id — ID записи п/п
  • table_id — id таблицы, о колонках которой хранится информация
  • visible — должна ли быть данная колонка видна
  • caption — название колонки, которое задается пользователем
  • name_ — наименование колонки, которое задается при создании таблицы

[pastacode lang=»sql» manual=»CREATE%20TABLE%20table_names%0A(%0Aid%20serial%20NOT%20NULL%2C%0Aname_%20character%20varying%20NOT%20NULL%2C%0ACONSTRAINT%20table_names_pkey%20PRIMARY%20KEY%20(id)%2C%0ACONSTRAINT%20table_names_name__key%20UNIQUE%20(name_)%0A)» message=»» highlight=»» provider=»manual»/]

А это, собственно, та таблица, где хранятся наименования таблиц, для которых нам надо выставить некие настройки.

Для динамического создания виджетов (пусть в нашем примере это будут виджеты классов QLabel и QLineEdit — подпись и поле ввода) на форме разместим объект QGridLayout, куда мы будем «пихать» виджеты. Я еще делаю такой трюк: помещаю в layout объекты в ряд в таком количестве, как хочу видеть результат:

Динамическое создание виджетов на форме в Qt

Далее эти два виджета делаю невидимыми:

[pastacode lang=»cpp» manual=»ui-%3Elabel-%3EsetVisible(false)%3B%0Aui-%3ElineEdit-%3EsetVisible(false)%3B» message=»» highlight=»» provider=»manual»/]

Для того, чтобы не просто разместить виджеты на форме, но и потом брать из них информацию для наших нужд, объявим в отделе private класса формы объект класса QVector<QLineEdit*> lineEdits.

Теперь приступим непосредственно к динамическому созданию виджетов.

[pastacode lang=»cpp» manual=»QSqlQuery%20query%3B%0A%2F%2F%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BC%20%D0%B2%D1%8B%D0%B1%D0%BE%D1%80%D0%BA%D1%83%20%D0%BD%D0%B5%D0%BE%D0%B1%D1%85%D0%BE%D0%B4%D0%B8%D0%BC%D1%8B%D1%85%20%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9%20%D0%B8%D0%B7%20%D0%B1%D0%B0%D0%B7%D1%8B%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%0Aif%20(!query.exec(QString(%22select%20column_id%2C%20caption%2C%20name_%2C%20visible%20from%20table_settings%20%22%0A%22where%20%22%0A%22table_id%20%3D%20(select%20id%20from%20table_names%20where%20%22%0A%22name_%20%3D%20’products’)%20%22%0A%22order%20by%20column_id%22)))%0AqDebug()%20%3C%3C%20query.lastError().text()%3B%20%0Awhile%20(query.next())%20%7B%20%0A%09QLabel%20*newLabel%20%3D%20new%20QLabel(this)%3B%20%2F%2F%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D0%BA%D0%BE%D0%B5%20%D0%BD%D0%B0%D0%B8%D0%BC%D0%B5%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%BA%D0%BE%D0%BB%D0%BE%D0%BD%D0%BA%D0%B8%20newLabel-%3EsetText(query.value(1).toString()%2B%22%3A%22)%3B%0A%09newLabel-%3EsetObjectName(%22label%22%2Bquery.value(2).toString())%3B%0A%09%2F%2F%D0%B2%D0%B8%D0%B4%D0%B8%D0%BC%D1%8B%D0%B9%20%D0%B2%20%D0%B7%D0%B0%D0%B2%D0%B8%D1%81%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8%20%D0%BE%D1%82%20%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%20visible%20%D0%B2%20%D1%80%D0%B5%D0%B7%D1%83%D0%BB%D1%8C%D1%82%D0%B0%D1%82%D0%B0%D1%85%20%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0%0A%09newLabel-%3EsetVisible(query.value(3).toBool())%3B%0A%09%2F%2F%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%89%D0%B0%D0%B5%D0%BC%20%D0%B2%20layout%0A%09ui-%3EwidgetsLayout-%3EaddWidget(newLabel)%3B%20%2F%2FQGridLayout%0A%09QLineEdit%20*newEdit%20%3D%20new%20QLineEdit(this)%3B%0A%09newEdit-%3EsetObjectName(query.value(2).toString())%3B%0A%09newEdit-%3EsetVisible(query.value(3).toBool())%3B%0A%09ui-%3EwidgetsLayout-%3EaddWidget(newEdit)%3B%0A%09%2F%2F%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%BB%D1%8F%D0%B5%D0%BC%20%D0%B2%20%D0%B2%D0%B5%D0%BA%D1%82%D0%BE%D1%80%0A%09lineEdits.push_back(newEdit)%3B%0A%7D%0A%2F%2F%D0%BF%D0%BE%D0%B4%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0%20%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0%20%D1%84%D0%BE%D1%80%D0%BC%D1%8B%20%D0%B2%20%D0%B7%D0%B0%D0%B2%D0%B8%D1%81%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8%20%D0%BE%D1%82%20%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BD%D0%B0%20%D0%BD%D0%B5%D0%B9%20%D0%B2%D0%B8%D0%B4%D0%B6%D0%B5%D1%82%D0%BE%D0%B2%0Athis-%3Eresize(this-%3EsizeHint())%3B» message=»» highlight=»» provider=»manual»/]

Динамическое создание виджетов на форме в Qt

Чтобы обратится к отдельному объекту в векторе, достаточно указать его индекс:

[pastacode lang=»cpp» manual=»for%20(int%20i%20%3D%200%3B%20i%20%3C%20lineEdits.size()%3B%20%2B%2Bi)%0A%09qDebug()%20%3C%3C%20lineEdits%5Bi%5D-%3EobjectName()%20%3C%3C%20%22%20-%20%22%20%3C%3C%20lineEdits%5Bi%5D-%3Etext()%3B» message=»» highlight=»» provider=»manual»/]

Более элегантная и универсальная версия этого метода представлена здесь: Динамическое создание виджетов Qt. QGridLayout