Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
Господа, будьте снисходительны, не бросайтесь сразу штрафовать за, как вам кажется, глупые вопросы - beginners на то и beginners.
Firebird, SQL и битовая маска 27.03.08 13:48 [Den]
Автор: Ustin <Ustin> Статус: Elderman Отредактировано 09.07.08 20:32 Количество правок: 4
|
Поиск в инете отдаёт мусор, не относящийся к делу - возможно потому, что мои знания в вопросе близки к 0.
Необходимо сделать запрос, который отдаёт данные на основании битовой маски, что-то вроде
select * from main where (eventsource or 65536 = eventsource), конструкция в скобках возвращает "unknown token".
В каком направлении копать? Можно ли обойтись без написания\использования процедур?
База FireBird 1.5, 2.
Заранее благодарю
[UPD]
Крайне корявое бюджетное решение найдено:
select *
from main where (
cast (eventcode/(65536*2) as smallint)*2 -
cast (eventcode/65536 as smallint) =1 )
---
Нет ли в SQL более элегантного способа?
|
|
Решение на триггерах, всем спасибо 09.07.08 20:32
Автор: Ustin <Ustin> Статус: Elderman
|
Создаём таблицу с полями для каждого развёрнутого битмаск и
CREATE TRIGGER MAINCHR_BI FOR MAINCHR
ACTIVE BEFORE INSERT POSITION 0
as
begin
new.es_etype =div(new.eventsource,16777216);
new.es_softcode =div(mod(new.eventsource,16777216),65536);
new.es_event =mod(new.eventsource,65536);
,,,
new.ec_etype =div(new.eventcode,16777216);
new.ec_softcode =div(mod(new.eventcode,16777216),65536);
new.ec_event =mod(new.eventcode,65536);
,,,
end
А дальше создаём индекс по нескольким полям в зависимости от задач. Дёшево, сердито и работает достаточно быстро
|
|
Только не 65536, а 65535 (если имеется ввиду unsigned smallint) 27.03.08 17:44
Автор: Den <Денис Т.> Статус: The Elderman
|
|
| |
Это не меняет кривизны решения. А почему? Ведь кастится получившийся в результате деления smallint (если исходное поле - int) 27.03.08 18:03
Автор: Ustin <Ustin> Статус: Elderman Отредактировано 27.03.08 18:09 Количество правок: 1
|
|
| | |
Только надо учесть, что любой целочисленный тип firebird - signed [upd2] 27.03.08 18:31
Автор: Den <Денис Т.> Статус: The Elderman Отредактировано 27.03.08 18:53 Количество правок: 5
|
Реализация SQL на FireBird'е не имеет битовых операторов и видимо, твое корявое решение - РЕШЕНИЕ
[upd]
Какая именно перед тобой задача?
Установить в полученном eventcode 16-ый бит и сравнить?
[upd2]
Попробуй еще такой вариант:
DECLARE EXTERNAL FUNCTION BIN_OR
INTEGER, INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT ’IB_UDF_bin_or’ MODULE_NAME ’ib_udf’;
---
|
| | | |
Ух ты! Это как? [upd2] 28.03.08 09:19
Автор: Ustin <Ustin> Статус: Elderman Отредактировано 28.03.08 10:10 Количество правок: 2
|
> Реализация SQL на FireBird'е не имеет битовых операторов и > видимо, твое корявое решение - РЕШЕНИЕ :(
> [upd] > Какая именно перед тобой задача? > Установить в полученном eventcode 16-ый бит и сравнить? Нет, задача выбирать по произвольной битовой маске, типа
select * from main where (isbitset(eventcode,bitmask)=true)
> [upd2] > Попробуй еще такой вариант: > > DECLARE EXTERNAL FUNCTION BIN_OR
> INTEGER, INTEGER
> RETURNS INTEGER BY VALUE
> ENTRY_POINT ’IB_UDF_bin_or’ MODULE_NAME ’ib_udf’;
> ---
Ух ты! Пасибо. Где такую штуку писать чтобы заработало? Как простой запрос не катит, простите, я туплю.
[UPD]: Катит, это я не прав, сорри... Разобрался с udf - библиотеками внешних функций, которые регистрируются путём выполнения запроса вида как выше. Если я правильно понял, это просто dll, которая просто экспортит функции, а FireBird подхватывает возвращаемые значения? Есть ли какие-нибудь особенности их написания, а лучше доки по написанию таких штук\механизму их работы?
[UPD2]: Гуру БД послали меня куда подальше с моими битовыми масками, сказав, что любой селект с where по битовой маске приведёт к селекту всего чего можно с верификацией каждой записи, то есть работать это будет медленно. Механизм меняться не будет, так как плодить столбцы ну совсем никак не хочется, найдено
Решение, специфичное для моей задачи:
1) Использование "историйной" таблицы - когда данные существуют больше определённого времени - переносим их в историю, обращения к которой в силу специфики происходит достаточно редко и не сильно критично по времени
2) Введение в интерфейсе принудительных ограничений на объём выбираемых данных типа замены select на select first 10000
|
| | | | |
Тогда уж так: 28.03.08 13:10
Автор: Den <Денис Т.> Статус: The Elderman Отредактировано 28.03.08 13:11 Количество правок: 1
|
> Нет, задача выбирать по произвольной битовой маске, типа > select * from main where (isbitset(eventcode,bitmask)=true)
Тогда уж так:
SELECT * FROM main WHERE Bin_and(eventcode,bitmask) <> 0
Маскирование битов выполняется побитовым AND, а не OR.
> [UPD]: Катит, это я не прав, сорри... Разобрался с udf - > библиотеками внешних функций, которые регистрируются путём > выполнения запроса вида как выше. Если я правильно понял, > это просто dll, которая просто экспортит функции, а > FireBird подхватывает возвращаемые значения? Есть ли > какие-нибудь особенности их написания, а лучше доки по > написанию таких штук\механизму их работы?
Это обычные DLL'ки с обычными функциями, которые подхватываются не сложнее чем в MS VB. Немного об этом есть в приведенной ниже ссылке.
Иногда, при их написании необходимо соблюдать некоторые правила, особенно те, что касаются выделения памяти (имеется ввиду выделение (malloc) памяти через менеджер памяти IB).
> [UPD2]: Гуру БД послали меня куда подальше с моими битовыми > масками, сказав, что любой селект с where по битовой маске > приведёт к селекту всего чего можно с верификацией каждой > записи, то есть работать это будет медленно.
Не факт! Они могут ошибаться.
Любое сравнение в БД использует вызов функций, зачастую находящихся в ядре сервера БД. При использовании определенных пользователем функций (UDF), DLL с этими функциями становиться т.н. in-proc сервером (используя терминологию COM), потому как выполняется в контексте загрузившего процесса и в одном с ним адресном пространстве.
> Механизм меняться не будет, так как плодить столбцы > ну совсем никак не хочется, найдено > Решение, специфичное для моей задачи: > 1) Использование "историйной" таблицы - когда данные > существуют больше определённого времени - переносим их в > историю, обращения к которой в силу специфики происходит > достаточно редко и не сильно критично по времени > 2) Введение в интерфейсе принудительных ограничений на > объём выбираемых данных типа замены select на select first > 10000
Все же не совсем понимаю в чем суть, но уверен, что у твоей задачи есть масса элегантных решений.
http://www.ibphoenix.com/downloads/60DevGuide.zip
|
| | | | | |
Спасибо! 28.03.08 15:42
Автор: Ustin <Ustin> Статус: Elderman
|
|
|
|