Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» InterBase и FireBird: вопросы по работе и их решение

Автор: vetal71
Дата сообщения: 22.01.2014 07:43
всем доброго времени суток. firebird 2.5.
пишу хранимую процедуру. в теле процедуры конструкция for select ... from ... where ... do. В зависимости от передаваемого параметра (варианта расчета) в конструкции меняется условие where. Вопрос в том, как реализовать выборку без переписывания for select... n-го количества раз.
Автор: exteris
Дата сообщения: 22.01.2014 10:29
vetal71
Зависит от того, что вы пишете в where. В некоторых случаях помогают конструкции типа - where x=iif(:par=1,y,z)
Либо формирование запроса динамически и execute statement.
Автор: vetal71
Дата сообщения: 22.01.2014 11:03
exteris
нет. в моем случае так не прокатит.
if (par=1) then
where a=:a and b=:b;
if (par=2) then
where b=:b and c=:c;
... примерно так.
Автор: Coltrain
Дата сообщения: 22.01.2014 14:12
vetal71
where ((:param = 1) and (<все условия предиката для знач. пар. = 1>))
or ((:param = 2) and (<все условия предиката для знач. пар. = 2>))
...
or ((:param = n) and (<все условия предиката для знач. пар. = n>))

подойдет?
Автор: vetal71
Дата сообщения: 22.01.2014 14:35
Coltrain
спасибо за совет. надо попробовать.
Автор: vetal71
Дата сообщения: 22.01.2014 20:54
exteris
Coltrain
решил задачу используя конструкцию
for execute statement <statement> into ... do
всем спасибо
Автор: Maximus777
Дата сообщения: 07.02.2014 18:49
Друзья! Направьте на путь истинный. Как в ibase делаются несколько запросов? Делаю Insert и следом update. Первый отрабатывает, второй нет. Строка сформирована правильно (если закомментить первый запрос, то второй отрабатывает). Подозреваю, что я просто не знаю порядок действий. Изучаю методом тыка, уж звиняйте, если вопрос слишком тупой.


Код: $stmt = 'INSERT INTO CLIENT_CATALOG (ITEM_ID,ITEM_NAME,ITEM_CONTACTS,ITEM_DATA,ITEM_CONTACT_NAME,ITEM_CONTACT_PROFESSION,ITEM_KOMPLEKT,ITEM_DATA_NEXT,ITEM_KOMM
VALUES (GEN_ID(id_gen,1),\''.$_POST['company'].'\',\''.$_POST['tel'].'\',\''.date("Y-m-d H:i:s").'\',\''.$_POST['fio'].'\',\''.$_POST['proff'].'\',\''.$cmpl.'
$_POST['commtext'].'\',\''.$otv.'\','.$_POST['status'].','.$tip.')';

$result = ibase_query($res, $stmt) or die(ibase_errmsg());

$stmt = 'UPDATE CLIENT_CATALOG SET ITEM_STATUS = \'1\' WHERE ITEM_ID = \''.$_POST['tag'].'\'';

$result = ibase_query($res, $stmt) or die(ibase_errmsg());
Автор: noisy
Дата сообщения: 07.02.2014 19:18
Maximus777

а если попробывать:

Код: $tr = ibase_trans(IBASE_WRITE || IBASE_NOWAIT, $res);

$stmt = 'INSERT INTO CLIENT_CATALOG (ITEM_ID,ITEM_NAME,ITEM_CONTACTS,ITEM_DATA,ITEM_CONTACT_NAME,ITEM_CONTACT_PROFESSION,ITEM_KOMPLEKT,ITEM_DATA_NEXT,ITEM_KOMM
VALUES (GEN_ID(id_gen,1),\''.$_POST['company'].'\',\''.$_POST['tel'].'\',\''.date("Y-m-d H:i:s").'\',\''.$_POST['fio'].'\',\''.$_POST['proff'].'\',\''.$cmpl.'
$_POST['commtext'].'\',\''.$otv.'\','.$_POST['status'].','.$tip.')';

$result = ibase_query($tr, $stmt);
if ($result)
    ibase_commit($tr);
else {
    ibase_errmsg();
    ibase_rollback($tr);
}


$tr = ibase_trans(IBASE_WRITE || IBASE_NOWAIT, $res);
$stmt = 'UPDATE CLIENT_CATALOG SET ITEM_STATUS = \'1\' WHERE ITEM_ID = \''.$_POST['tag'].'\'';

$result = ibase_query($tr, $stmt);
if ($result)
    ibase_commit($tr);
else {
    ibase_errmsg();
    ibase_rollback($tr);
}
Автор: Maximus777
Дата сообщения: 07.02.2014 19:53
Итить! Работает!

Благодарю! Буду морщить лоб и напрягать осознание, чтобы разобраться в причинах.

noisy

Цитата:
ibase_prepare - ibase_execute

Тут ведь вот какое дело. Какой пример первый попался, тот и пришлось использовать. А тепер на каждой страничке читаю такой же совет. Видимо, надо прислушаться. Попробую. Мне б ещё примеров помясисьтее, а то в документации такие куцые
Автор: noisy
Дата сообщения: 07.02.2014 20:38
у PHP плохо организовано управление транзакциями IB/FB по умолчанию,
поэтому совет при работе ставить свои транзакции на чтение и обновление
для себя сделал такой класс для работы с FB
[more]
<?php

class fbsql_db {

var $session;
var $debug = false;

// Конструктор класса сервер, база данных, пользователь, пароль
function fbsql_db($sqlserver, $database, $sqluser='SYSDBA', $sqlpassword='masterkey', $charset = 'WIN1251', $persistency = true) {

$this->user = $sqluser;
$this->password = $sqlpassword;
$this->server = $sqlserver;
$this->dbname = $database;

if($persistency) {
$this->session = ibase_pconnect($this->server.":".$this->dbname, $this->user, $this->password, $charset);
}
else {
$this->session = ibase_connect($this->server.":".$this->dbname, $this->user, $this->password, $charset);
}

return $this->session;
}

// удаление объекта
function __destruct() {
if($this->session)
{
$result = @ibase_close($this->session);
return $result;
}
else
{
return false;
}
}

// Выборка всего результата в ассоциативный массив
function select_assoc_all($sql = "") {
if($sql != "") {
if ($this->debug) { echo $sql.PHP_EOL;}
$transaction = ibase_trans(IBASE_READ + IBASE_NOWAIT, $this->session);
$statement = ibase_query($transaction, $sql);
$result = array();
$i = 0;
while ($row = ibase_fetch_assoc($statement)) {
$result[$i] = $row;
$i++;
}
ibase_free_result($statement);
ibase_rollback($transaction);
return $result;
}
else {
return FALSE;
}
}

// Выполнение UPDATE или INSERT инструкций
function exec_modify_sql($sql = "") {
if($sql != "") {
if ($this->debug) echo $sql.PHP_EOL;
$transaction = ibase_trans(IBASE_WRITE + IBASE_NOWAIT, $this->session);
$statement = ibase_query($transaction, $sql);
if ($statement) ibase_commit($transaction);
return $statement;
}
else {
return FALSE;
}
}

// Выполнение UPDATE или INSERT инструкций
function exec_modify_sql_with_result($sql = "") {
if ($this->debug) {
echo 'exec_modify_sql_with_result - '. $sql.PHP_EOL;
}
if($sql != "") {
$transaction = ibase_trans(IBASE_WRITE + IBASE_NOWAIT, $this->session);
$statement = ibase_query($transaction, $sql);
$result = array();
$i = 0;
while ($row = ibase_fetch_assoc($statement)) {
$result[$i] = $row;
$i++;
}
ibase_commit($transaction);
return $result;
}
else {
return FALSE;
}
}

function close() {
if($this->session) {
$result = @ibase_close($this->session);
return $result;
}
else {
return false;
}
}
} // class fbsql_db
[/more]
Автор: Maximus777
Дата сообщения: 07.02.2014 20:58
noisy
Спасибо!
Автор: Maximus777
Дата сообщения: 10.02.2014 12:25
Подсобите ещё с одной задачей. В таблице есть поле "Телефон". Заполнено, как звёзды встанут. С пробелами, с дефисами. Чтобы организовать поиск по телефону, добавляю в таблицу ещё одно поле. Теперь надо взять инфу с первого поля, очистить её от пробелов и дефисов (оставив только цифры и запятые) и прописать в новое поле. Хотелось бы как-то с одного раза всех зайцев ухлопать.
Автор: noisy
Дата сообщения: 10.02.2014 13:08
Maximus777

как-то так [more]

create or alter procedure EXTRACT_ALL_DIGITS (
A_VALUE D_VARCHAR255)
returns (
DIGITS D_VARCHAR255)
AS
declare variable i d_integer;
declare variable j d_integer;
declare variable d d_char1;
begin

j = CHAR_LENGTH(a_value);
i = 1;
DIGITS = '';
while (i <= j) do begin
d = substring(a_value FROM i FOR 1);
IF (d BETWEEN '0' AND '9')
then DIGITS = DIGITS ||d;
i = i + 1;
end

suspend;
end

update Table t
set phone = select DIGITS from EXTRACT_ALL_DIGITS( t.phone) ;

[/more]
Автор: YuriyRR
Дата сообщения: 10.02.2014 23:28
Maximus777
У меня в Rfunc добавлено

char* EXPORT fn_extract_phone(ARG(char*, s))
ARGLIST(char *s)
{
    unsigned char *f = s;
    unsigned char *c = s;

    while(*c) {
if(isdigit(*c)) *f++=*c;
c++;
}
*f = '\0';
    return s;
}
Автор: Maximus777
Дата сообщения: 11.02.2014 19:51
Спасибо за ответы. Вопрос дублирования и очистки продублированного поля решил врукопашную. Несколько запросов типа:


Код: update CLIENT_CATALOG set item_clear_phone = REPLACE(item_clear_phone, '-', '');
Автор: noisy
Дата сообщения: 11.02.2014 20:18
Maximus777

не советовал бы использовать UDF если можно обойтись родными средствами сервера,
а RFUNC тем более не советую, старая эта либа уже
современная замена RFUNC - AUDFL https://www.assembla.com/spaces/audfl_rfunc/documents
Автор: YuriyRR
Дата сообщения: 11.02.2014 23:28
noisy

Цитата:
современная замена RFUNC - AUDFL

Спасибо, посмотрим.
Автор: Maximus777
Дата сообщения: 12.02.2014 07:04
noisy
мне пока ничего не угрожает, т.к. базу я почистил несколькими запросами, а далее данные в базу уже будут попадать, в предназначенное поле, очищенными. Очисткой будет заниматься js или php. Но за советы, в любом случае, благодарю.
Автор: Chandr24
Дата сообщения: 19.02.2014 14:05
Установил Interbase XE3 Developer Edition. Сервер Interbase нормально работает, с помощью IBConsole создал свою базу данных, подключился к ней и таблицы посмотрел.
Но в среде RAD Studio XE5 с помощью компонента TIBDatabase подключиться к БД не получается, "unavailable database".
Если программу запустить из под среды (под отладчиком или без), то БД тоже не открывается с тем же сообщением.
Если же программу запустить значком с рабочего стола, то все ОК, база открывается и редактируется.
user_name и password и в параметры TIBDatabase заносил, и руками указывал - результат не меняется.
Подскажите, как справиться с проблемой, а то без среды отлаживаться тяжело.
Автор: YuriyRR
Дата сообщения: 19.02.2014 17:34
Chandr24
Клиентская dll должна быть видна ну и под 7кой host нужно указывать. по крайней мере localhost
Автор: Chandr24
Дата сообщения: 20.02.2014 07:15
YuriyRR
"Клиентская dll" (gds32.dll если я правильно понял), разумеется, видна, ведь запущенная не из-под среды программа с ней нормально работает. У меня установлена Windows 8, только я не понял, где именно "host нужно указывать. по крайней мере localhost" и зачем? Можно чуть-чуть подробнее?
Автор: YuriyRR
Дата сообщения: 20.02.2014 14:46
Chandr24
SERVER:G:\BASES\BASЕ.FDB - пример коннекта к WIN
SERVER:/usr/bases/base.fdb - пример коннекта к LINUX
localhost:g:\!BASES\base.fdb локальный компьютер
KVARTP/3060:c:\PASSPORT\BASE\base.FDB на другой порт

Автор: Chandr24
Дата сообщения: 21.02.2014 06:05

Цитата:
YuriyRR
SERVER:G:\BASES\BASЕ.FDB - пример коннекта к WIN
SERVER:/usr/bases/base.fdb - пример коннекта к LINUX
localhost:g:\!BASES\base.fdb локальный компьютер
KVARTP/3060:c:\PASSPORT\BASE\base.FDB на другой порт

Уважаю ! Спасибо огромное, после дописывания префикса localhost: действительно заработало!
Автор: xpin2013
Дата сообщения: 25.02.2014 16:16
Аномальный день. 2 глюка FB сервера за 2 часа.
1) Выяснили LEFT JOIN возвращает то что должен возвращать JOIN. Он действительно склеивает обе таблички. JOIN возвращает пусто, хотя нулевая запись есть и везде стоят нули. Я сделал вывод что кривой индекс и прописал Бэкап-Рестор. Бекап-Рестор действительно помог, но я понял, что JOIN и LEFT JOIN это два разных алгоритма!...

2) Баг с Доменами. Другой программист добавил два INT NOT NULL DEFAULT 0 CHECK >=0 поля в табличку, которая без триггеров, без PRIMARY KEY без форейнов без индексов без BLOB полей! После этого, когда редактируем данные и Post, а не Commit - вылетает ошибка "BLOB field not found". Этого глюка я вообще не понял и прописал - убить оба поля и создать заново. - Ошибка исчезла!...

3) У меня был трамвайный билет номер 133368 - и компьютер работал без капризов.


У меня два вопроса
- Что такое ошибка "BLOB field not found".
и
- Правда ли что JOIN и LEFT JOIN два разных алгоритма?

Добавлено:
ps (при LEFT JOIN тоже используются индексы)
Автор: ant0ni02004
Дата сообщения: 25.02.2014 16:51
xpin2013

Цитата:
Правда ли что JOIN и LEFT JOIN два разных алгоритма?

именно этот вопрос здесь недавно обсуждался, полистайте пару страниц назад
Автор: noisy
Дата сообщения: 25.02.2014 16:53
xpin2013

о "BLOB field not found"

я думаю без схемы БД и запросов никто помочь не сможет.

по JOIN можно почитать на wiki http://ru.wikipedia.org/wiki/Join_%28SQL%29
а вот еще и в картинках http://www.k-press.ru/cs/2009/3/join/join.asp

JOIN и LEFT JOIN - разные алгоритмы
Автор: xpin2013
Дата сообщения: 25.02.2014 17:54
noisy

Цитата:
я думаю без схемы БД и запросов никто помочь не сможет.

Когда в табле нет примари, то IBExpert генерит на редактирование запрос
Update where Все филды = старые филды.
Таблица
id = domen int
name = varchar правильный коллате
addFild1 = domen int
addFild2 = domen int.


Цитата:
я думаю без схемы БД и запросов никто помочь не сможет.

Нет запросов - редактируем в IBExpert. Я Вам таки скажу - это глюк доменов, не первый раз.
Автор: ant0ni02004
Дата сообщения: 25.02.2014 20:38
xpin2013

Цитата:
это глюк доменов, не первый раз

backup+restore может помочь в этой ситуации
Автор: OXDBA
Дата сообщения: 26.02.2014 07:26
xpin2013
Очень похоже на неудачную попытку залезть в системные таблицы, при изменении домена, IBE раньше этим грешил, сейчас не знаю. Нужно внимательно смотреть на формируемый запрос при изменении метаданных и избегать запросов типа

Код: update RDB$FIELDS set ...
Автор: xpin2013
Дата сообщения: 26.02.2014 10:38
OXDBA
Да, да. Но только он не лазил в RDB. Просто они (системные таблицы) были включены для просмотра. Бэкап-рестор не понадобился, мы просто удалили оба филда и создали их заного. Но глюк с доменами видимо бывает, я как то создал NOT NULL филд и после ошибки обнаружил, что в этом поле записи NULL. Когда я не использую доменов ничего подобного не происходит.

Добавлено:
OXDBA
А можно ли в системных таблицах хранить свои данные? Всего спрятать ключик к базе - пометить.

Добавлено:
Решил сам проверить - изначально глупая затея была у моих коллег. При первом же backup-restore вся системная информация теряется. Это техподдержка будет вынуждена мучатся очень сильно.

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465

Предыдущая тема: Сравнение двух строк


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.