Как записать выполненный SQL

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Klyk
Сообщения: 100
Зарегистрирован: 26 окт 2004, 23:28

Как записать выполненный SQL

Сообщение Klyk » 26 окт 2004, 23:46

Вопрос такой:
Необходимо, чтобы при обновлении (добавлениеии, удалении) записи, запрос, который был выполнен, записывался в txt.

Может в триггерах чего написать.... а чего?

(IB7, Delphi7)

Andrew Kruchinin
Сообщения: 6
Зарегистрирован: 27 окт 2004, 06:35

Re: Как записать выполненный SQL

Сообщение Andrew Kruchinin » 27 окт 2004, 06:49

Klyk писал(а):Вопрос такой:
Необходимо, чтобы при обновлении (добавлениеии, удалении) записи, запрос, который был выполнен, записывался в txt.

Может в триггерах чего написать.... а чего?

(IB7, Delphi7)
Ну смотря для чего. Если правильно понял то использовать AfterExecute (и подобные для нужных вещей) в самой программе. И пиши что душе угодно и куда хочешь.

А в триггерах ты ничего не получишь, текста запроса там нет. Хотя можно конечно записывать измененные поля к примеру, но условия в WHERE ты однозначно потеряешь.

P.S. Кстати, данный вариант катит для ФИБов вроде бы только. Для IBX в TIBSQL придется после выполнения запроса писать сброс текста. А вообще непонятная задача какая-то. Зачем это нужно?

Deniz
Сообщения: 7
Зарегистрирован: 27 окт 2004, 06:38

Сообщение Deniz » 27 окт 2004, 07:14

Например для логирования действий можно писать во внешнюю таблицу например так:

Код: Выделить всё

create trigger au_triggername for tablename after update position 0
as 
declare variable s_sql varchar(2000);
declare variable fields_count integer;
begin
  s_sql = 'update table name set ';
  fields_count = 0;
  if (new.field1 <> old.field1) then begin
      select :s_sql || ' field1 = ' || cast(new.field1 as varchar(20))
          from rdb$database into :s_sql;
      fields_count = 1;
  end
  if (new.field2 <> old.field2) then begin
      if (fields_count > 0) then s_sql = s_sql || ',';
      select :s_sql || ' field2 = ' || cast(new.field2 as varchar(20))
          from rdb$database into :s_sql;
      fields_count = fields_count + 1;
  end
...
  select :s_sql || ' where PKFIELD = ' || cast(old.pkfield as varchar(20))
  if (fields_count > 0) then
      insert into ext_table(..., fields_changed, sql_type, sql_text) values (..., fields_count, 'update', :s_sql);
end
примерно так реализовать для update, вероятно есть ошибки(для строковых полей нужно еще и кавычки в s_sql засунуть), но ...
Для сохранения в текстовый файл, на сервере можно использовать UDF, которая получает необходимые параметры и сохраняет их в определенную папку, тогда добавление во внешнюю таблицу заменить на:

Код: Выделить всё

select udf_save_to_txt_file(..., :s_sql) from rdb$database into :fields_count;
в fields_count можно передавать код завершения udf.
Можно еще свой монитор написать.

Гость

Сообщение Гость » 27 окт 2004, 07:22

Deniz писал(а):Например для логирования действий можно писать во внешнюю таблицу например так
[skiped]
примерно так реализовать для update, вероятно есть ошибки(для строковых полей нужно еще и кавычки в s_sql засунуть), но ...

Можно еще свой монитор написать.
Ага. Я с монитором не работал, но что-то подсказывает мне что отследить обновление данных с его помощью немного невозможно, т.к. существуют такие вещи как транзакции и откаты. но если нужно сохранять все запросы которые идут из программы к серверу - то это да, единственный путь наверное (кроме вставки в саму прогу соответствующего кода).

По поводу условий я уже писал, через триггеры мы получим сохранение не _запроса_ (как было спрошено в самом вопросе) а только _данных_, что является не совсем чем чем нужно.

Andrew Kruchinin
Сообщения: 6
Зарегистрирован: 27 окт 2004, 06:35

Сообщение Andrew Kruchinin » 27 окт 2004, 07:24

Сорь, про авторизацию забыл. А т.к. переходил по ссылке из письма то получилось что не подписался :-(

Deniz
Сообщения: 7
Зарегистрирован: 27 окт 2004, 06:38

Сообщение Deniz » 27 окт 2004, 07:42

Andrew Kruchinin писал(а): ... что является не совсем чем чем нужно.
Из первого сообщения Автора:
Klyk писал(а): ... при обновлении (добавлениеии, удалении) записи ...
хочу обратить внимание на слово записи если Автор уточнит свой вопрос, тогда можно будет говорить о несостоятельности того или иного варианта.

Klyk
Сообщения: 100
Зарегистрирован: 26 окт 2004, 23:28

Сообщение Klyk » 27 окт 2004, 07:50

На самом деле зачем это всё надо.
Есть 2 БД, связь между которыми - невозможна, следовательно репликатор неподходит. А изменения в одной БД надо отображать в другой. Есть возможность передачи только текстовых файлов (раз в сутки).
Вот я и думал создавать SQL скрипты при изменении данных в одной БД и выполнять этот скритп для изменения второй БД.
Может есть и другие идеи...

Andrew Kruchinin
Сообщения: 6
Зарегистрирован: 27 окт 2004, 06:35

Сообщение Andrew Kruchinin » 27 окт 2004, 07:52

Deniz писал(а):
Andrew Kruchinin писал(а): ... что является не совсем чем чем нужно.
Из первого сообщения Автора:
Klyk писал(а): ... при обновлении (добавлениеии, удалении) записи ...
хочу обратить внимание на слово записи если Автор уточнит свой вопрос, тогда можно будет говорить о несостоятельности того или иного варианта.
Согласен, тем более что более полная цитата
Необходимо, чтобы при обновлении (добавлениеии, удалении) записи, запрос, который был выполнен, записывался в txt.
вносит полный разброд :)

Andrew Kruchinin
Сообщения: 6
Зарегистрирован: 27 окт 2004, 06:35

Сообщение Andrew Kruchinin » 27 окт 2004, 08:00

Klyk писал(а):На самом деле зачем это всё надо.
Есть 2 БД, связь между которыми - невозможна, следовательно репликатор неподходит. А изменения в одной БД надо отображать в другой. Есть возможность передачи только текстовых файлов (раз в сутки).
Вот я и думал создавать SQL скрипты при изменении данных в одной БД и выполнять этот скритп для изменения второй БД.
Может есть и другие идеи...
А, ну если так то в принципе ты можешь создавать конечно запросы из самих тригеров. но есть чреватости и подводные камни при таком подходе если что. Особенно если таблицы будут связаны ключами к примеру. Т.е. можно на такие грабли наступить что ой-ой-ой.

А почему репликтор не подходит? Тебе же нужна именно репликация, а то что нужно передавать текстовые файлы чем плохо? Собственно она самая родимая и получится.

P.S. Связь понятие довольно растяжимая :-) Это может быть и курьер на велосипеде с дискеткой ;)

Klyk
Сообщения: 100
Зарегистрирован: 26 окт 2004, 23:28

Сообщение Klyk » 27 окт 2004, 08:00

Согласен, тем более что более полная цитата

Цитата:
Необходимо, чтобы при обновлении (добавлениеии, удалении) записи, запрос, который был выполнен, записывался в txt.

вносит полный разброд
См. описание выше...

P.S. Или может я зря копаю, может всё гораздо проще...

Klyk
Сообщения: 100
Зарегистрирован: 26 окт 2004, 23:28

Сообщение Klyk » 27 окт 2004, 08:13

таблицы связанны...
Но, кто не рискует, то не пьёт шампанское....
А почему репликтор не подходит
.

Потому что курьер на велосипеле туда не доедет, а связь тока на несеолько секунд чтоб передать файлики.
Это всё равно что если бы тебе сказали: отправлять мыло один раз в день и аттачи только txt или ini или им подобные.

Andrew Kruchinin
Сообщения: 6
Зарегистрирован: 27 окт 2004, 06:35

Сообщение Andrew Kruchinin » 27 окт 2004, 08:14

Klyk писал(а): P.S. Или может я зря копаю, может всё гораздо проще...
То что Deniz предложил - как доктор прописал ;) Вроде бы то что тебе нужно.

Klyk
Сообщения: 100
Зарегистрирован: 26 окт 2004, 23:28

Сообщение Klyk » 27 окт 2004, 08:16

ну, попробовать, конечно можно....
ночь впереди :))

Deniz
Сообщения: 7
Зарегистрирован: 27 окт 2004, 06:38

Сообщение Deniz » 27 окт 2004, 08:19

Во как вопрос перевернулся :o
В принципе мой вариант подойдет, только вместо

Код: Выделить всё

update table set field1 = value where id between 10 and 15
у меня получится 6 одиночных запросов:

Код: Выделить всё

update table set field1 = value where id 10
update table set field1 = value where id 11
...
update table set field1 = value where id 15
что повлечет за собой сильное "разбухание" текстовика. С другой стороны если update очень серьёзный, и в присвоении, и в where много всяких условий(или не дай бог select из других таблиц), а в результате обрабатывается не много записей, то мой вариант будет быстрее отрабатывать.
Например:

Код: Выделить всё

update table set 
  field1 = (select count(*) from table2 t2 where (...) )
where id in (select distinct field1 from table3 where (...) )
может обрабатываться очень долго, в то время как набор

Код: Выделить всё

update table set field1 = value where id 10
update table set field1 = value where id 11
...
update table set field1 = value where id 15
скорее всего обработается за доли секунд
Можно использовать дату, время, тип операции и т.д. последнего изменения записи и написать програмку, которая выбирает всё с последнего переноса, и потом update в другую БД.

Deniz
Сообщения: 7
Зарегистрирован: 27 окт 2004, 06:38

Сообщение Deniz » 27 окт 2004, 08:27

:o Пока ответ писал столько постов появилось
Попробуй, о результатах должить сюда, тем более что еще нужно доделать и додумать кое-что по алгоритму.
И еще, по описанию работы
Klyk писал(а):На самом деле зачем это всё надо.
писать в txt не обязательно, можно в какую-нибудь табличку, и потом в программе select ... from table order by datetime_field что бы сохранить последовательность.
Удачи.

Klyk
Сообщения: 100
Зарегистрирован: 26 окт 2004, 23:28

Сообщение Klyk » 27 окт 2004, 08:31

не, запросов типа

Код: Выделить всё

update table set 
  field1 = (select count(*) from table2 t2 where (...) ) 
where id in (select distinct field1 from table3 where (...) )
скорее всего не будет.

Попробуем-с...
Что получится расскажу :))
Спасибо :)))

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 27 окт 2004, 09:38

Klyk писал(а):На самом деле зачем это всё надо.
Есть 2 БД, связь между которыми - невозможна, следовательно репликатор неподходит. А изменения в одной БД надо отображать в другой. Есть возможность передачи только текстовых файлов (раз в сутки).
Вот я и думал создавать SQL скрипты при изменении данных в одной БД и выполнять этот скритп для изменения второй БД.
блин, это и есть репликация. зачем тебе sql-скрипты??? Не морочь голову - в топике есть действительно интересные письма, но они тебе СОВСЕМ без надобности. потому что тебе надо просто обеспечить самую что ни на есть стандартную репликацию. Реплицируемые записи можно сбрасывать хоть в текстовый файл, затем в zip, и тащить к другой БД на дискете.

А "репликация" путем передачи SQL уже обсуждалась в e.p.i - ни для чего кроме как сохранения информации о том, какой клиент выдавал какой запрос, это не годится. т.е. лог SQL команд использовать для репликации НЕЛЬЗЯ.

В твоем же случае при мизерных (по кол-ву данных) изменениях в БД у тебя будет генериться огромное количество SQL, т.е. производительность просто увянет, особенно если в задаче будет update, обновляющий 100-200 записей одновременно (!).

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 27 окт 2004, 11:48

Deniz писал(а):Например для логирования действий можно писать во внешнюю таблицу например так:

Код: Выделить всё

create trigger au_triggername for tablename after update position 0
as 
begin
      ....
      insert into ext_table(..., fields_changed, sql_type, sql_text) values (..., fields_count, 'update', :s_sql);
end
Внимание, вопрос. Що будем делать с этой записью в external table в случае ежели за оным update последовал rollback транзакции, в которой он выполнялся?

Klyk
Сообщения: 100
Зарегистрирован: 26 окт 2004, 23:28

Сообщение Klyk » 27 окт 2004, 23:45

тебе надо просто обеспечить самую что ни на есть стандартную репликацию
и можно обойтись простым ibreplicator'ом ?

Klyk
Сообщения: 100
Зарегистрирован: 26 окт 2004, 23:28

Сообщение Klyk » 28 окт 2004, 00:01

P.S. И вообще, народ, посовоетуйте что почитать по репликации...
А то зачем она нужна - понимаю, а как оно работает...увы :((

Ответить