Архив метки: mysql

Как постранично (порционно) листать результат запроса в 1С (ака LIMIT x,y в MySQL)

Большая беда MSSQL и как следствие 1С — отсутствие возможности порционно листать записи результата запроса как в MySQL. В результате рождаются такие монстроузные алгоритмы как ниже (код не мой):

Функция GetNewsList(body, answer) Экспорт
	
	answer.error = Истина;
	answer.errortext = "Что-то пошло не так..";
	answer.result = "";
	
	Попытка
		page = ?(ЗначениеЗаполнено(body.page), Число(body.page), 1);
		Если page < 1 Тогда
			page = 1;
		КонецЕсли;
		
		nums = ?(ЗначениеЗаполнено(body.nums), Число(body.nums), 5);
		Если nums < 5 Тогда
			nums = 5;
		КонецЕсли;
		
		ПредДата = ТекущаяДата();
		ПредКод = "";
		Если page > 1 Тогда
			Запрос = Новый Запрос;
			Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 100
			               |	Хрюкости.Дата КАК Дата,
			               |	Хрюкости.Код КАК Код
			               |ПОМЕСТИТЬ тПредыдущих
			               |ИЗ
			               |	Справочник.ПоследниеСплетни КАК Хрюкости
			               |
			               |УПОРЯДОЧИТЬ ПО
			               |	Хрюкости.Дата УБЫВ,
			               |	Хрюкости.Код УБЫВ
			               |;
			               |
			               |////////////////////////////////////////////////////////////////////////////////
			               |ВЫБРАТЬ ПЕРВЫЕ 1
			               |	тПредыдущих.Дата КАК Дата,
			               |	тПредыдущих.Код КАК Код
			               |ИЗ
			               |	тПредыдущих КАК тПредыдущих
			               |
			               |УПОРЯДОЧИТЬ ПО
			               |	тПредыдущих.Дата,
			               |	тПредыдущих.Код";
			Запрос.Текст = СтрЗаменить(Запрос.Текст, "100", Формат((page - 1) * nums, "ЧДЦ=0; ЧН=; ЧГ="));
			Выборка = Запрос.Выполнить().Выбрать();
			Если Выборка.Следующий() Тогда
				ПредДата = Выборка.Дата;
				ПредКод = Выборка.Код;
			КонецЕсли;
		КонецЕсли;
		
		Запрос = Новый Запрос;
		Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 100
		               |	Хрюкости.Код КАК news_code,
		               |	Хрюкости.Дата КАК date,
		               |	Хрюкости.Наименование КАК name,
		               |	Хрюкости.Содержание КОНЕЦ КАК content,
		               |	Хрюкости.Изображение КАК image
		               |ИЗ
		               |	Справочник.ПоследниеСплетни КАК Хрюкости
		               |ГДЕ
		               |	(Хрюкости.Дата < &ПредДата)
		               |	ИЛИ
					   |	(Хрюкости.Дата = &ПредДата И Хрюкости.Код < &ПредКод)
		               |
		               |УПОРЯДОЧИТЬ ПО
		               |	Хрюкости.Дата УБЫВ,
		               |	Хрюкости.Код УБЫВ";
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "100", Формат(nums, "ЧДЦ=0; ЧН=; ЧГ="));
		Запрос.УстановитьПараметр("ПредДата", ПредДата);
		Запрос.УстановитьПараметр("ПредКод", ПредКод);
		Выборка = Запрос.Выполнить().Выбрать();
		
		РезМассив = Новый Массив;
		Пока Выборка.Следующий() Цикл
			РезСтрукт = Новый Структура("news_code, date, datestr, name, content, image");
			ЗаполнитьЗначенияСвойств(РезСтрукт, Выборка);
			РезСтрукт.datestr = Формат(Выборка.date, "ДФ='dd.MM.yyyy HH:mm:ss'");
			РезМассив.Добавить(РезСтрукт);
		КонецЦикла;
		
		ЕстьЕще = Ложь;
		Если РезМассив.Количество() > 0 Тогда
			КрайняяНовость = РезМассив[РезМассив.Количество() - 1];
			Запрос = Новый Запрос;
			Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1
			               |	Хрюкости.Код КАК news_code
			               |ИЗ
			               |	Справочник.ПоследниеСплетни КАК Хрюкости
			               |ГДЕ
			               |	(Хрюкости.Дата < &ПредДата)
			               |	ИЛИ
						   |	(Хрюкости.Дата = &ПредДата И Хрюкости.Код < &ПредКод)
			               |
			               |УПОРЯДОЧИТЬ ПО
			               |	Хрюкости.Дата УБЫВ,
			               |	Хрюкости.Код УБЫВ";
			Запрос.УстановитьПараметр("ПредДата", КрайняяНовость.date);
			Запрос.УстановитьПараметр("ПредКод", КрайняяНовость.news_code);
			ЕстьЕще = НЕ Запрос.Выполнить().Пустой();
		КонецЕсли;
		
		answer.result = Новый Структура("portion, havingmore", РезМассив, ЕстьЕще);
		answer.error = Ложь;
		answer.errortext = "";
		
	Исключение
		answer.errortext = ОписаниеОшибки();
	КонецПопытки;
	
	Возврат answer;
	
КонецФункции

Если вкратце, то алгоритм следующий:

  1.  Делаем выборку ВСЕХ записей, определяя, с какой записи было начало предыдущей страницы
  2. Начиная с этой записи, делаем выборку N записей
  3. Передаем результат

Интересно будет посмотреть как этот алгоритм будет вести себя при миллионах записей..

 

Восстановление только одной таблицы из бекапа MySQL

Довольно частая ситуация: есть бекап базы. Развертывать его целиком чтобы посмотреть данные одной таблицы? А если он большой это может занять продолжительное время. Есть вариант с использованием sed:

sed -n -e '/CREATE TABLE.*`usbox_services`/,/CREATE TABLE/p' 2020-07-07.sql  > usbox_services.sql

В результате выполнения будет сформирован файл содержащий только таблицу usbox_services. Ну а далее его уже заливаем стандартно..

MYSQL: <имя таблицы> is marked as crashed and should be repaired

В моем случае обошлось просто (Внимание! данные в таблице удаляются!):

shell> mysql db_name
mysql> SET AUTOCOMMIT=1;
mysql> TRUNCATE TABLE table_name;
mysql> quit

Если данные важны для сохранения,восстановить можно попробовать так:

myisamchk -r --update-state /var/lib/mysql/dbname/table_name.MYI

Интересное поведение mysql при выборке из таблицы содержащей NULL

Столкнулся с интересным поведением MySQL при выборке из таблицы содержащей NULL в качестве значения.  Очередной подвох однако.. Пусть например есть таблица:

mysql> select cat_idx,uuid from categories where tar_id=109 and common=0 and above=1 and archive=0;
+---------+------+
| cat_idx | uuid |
+---------+------+
|       0 | NULL |
|       5 | NULL |
|      10 | NULL |
|      11 | NULL |
|      15 | NULL |
|      28 | peni |
+---------+------+
6 rows in set (0.00 sec)

Хотим получить все значения не содержащие uuid=»peni». Логично было бы использовать такой запрос:

mysql> select cat_idx,uuid from categories where tar_id=109 and common=0 and above=1 and archive=0 and uuid<>"peni";
Empty set (0.00 sec)

Аааа. А куда делись остальные значения? А вот потому что с точки зрения MySQL правильно будет:


mysql> select cat_idx,uuid from categories where tar_id=109 and common=0 and above=1 and archive=0 and (uuid<>"peni" or uuid is null);
+---------+------+
| cat_idx | uuid |
+---------+------+
|       0 | NULL |
|       5 | NULL |
|      10 | NULL |
|      11 | NULL |
|      15 | NULL |
+---------+------+
5 rows in set (0.00 sec)


Вывод: при создании таблиц нужно стараться заполнять поля значениями «по умолчанию». Чтобы NULL не было в принципе. Тогда и возможной ошибки не будет.

 

mysql_virtual_alias_maps.cf is unavailable. unsupported dictionary type: mysql после обновления Postfix

После обновления части пакетов, обновился и postfix. После чего перестала отправляться/приниматься почта с ошибкой в логах:

mysql_virtual_alias_maps.cf is unavailable. unsupported dictionary type: mysql

Решение: отвалился модуль postfix-mysql. Порывшись так и не нашел как установить сиё через pkg install

Поставил posfix из портов, отметив модуль mysql

pkg remove postfix
cd /usr/ports/mail/postfix-sasl
make config
make install