Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Триггер на запрет удаления сборников

Доброго времени суток. Есть триггер, который должен запрещать удаление сборников, опубликованных в текущем году. При попытке удаления сборника, возникает ошибка "Mutating table". Читал, что можно избежать её, написав еще один дополнительный триггер, в котором я буду записывать код_издания, код_автора в глобальные переменные пакета, а уже потом использовать их.
Есть следующий код:
Oracle 11 SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CREATE OR REPLACE TRIGGER forbidDeleteDigest
before DELETE ON Edits
FOR EACH ROW
DECLARE
 
digestCount NUMBER;
forbidDelete EXCEPTION;
 
BEGIN
 
SELECT COUNT(Издания) INTO digestCount FROM (SELECT edits.edit_code AS Издания, COUNT(authors.author_code) AS Кол_авторов, exit_date AS Data
FROM edits,authors,edits_authors
WHERE edits.edit_code = edits_authors.edit_code AND authors.author_code = edits_authors.author_code AND TO_CHAR(exit_date,'yyyy') = TO_CHAR(SYSDATE,'yyyy')
GROUP BY edits.edit_code, exit_date
HAVING COUNT(authors.author_code) > 1);
 
IF (digestCount> 0) THEN RAISE forbidDelete;
END IF;
 
EXCEPTION
 
WHEN forbidDelete THEN
raise_application_error (-20000,'Запрещено! Попытка удалить сборник, изданный в текущем году.');
 
END;
Помогите реализовать запрет удаления сборников.

Структура таблицы "Издания":
Oracle 11 SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE TABLE  "EDITS" 
   (    "EDIT_CODE" CHAR(18) NOT NULL ENABLE, 
    "PUB_CODE" NUMBER(4,0) NOT NULL ENABLE, 
    "EDIT_NAME" VARCHAR2(40), 
    "GENRE" VARCHAR2(40), 
    "PRICE" NUMBER(6,0), 
    "COSTS" NUMBER(6,0), 
    "AMOUNT" NUMBER(6,0), 
    "CONDITION" VARCHAR2(40), 
    "EXIT_DATE" DATE, 
    "NOTE" VARCHAR2(200), 
     PRIMARY KEY ("EDIT_CODE", "PUB_CODE")
  USING INDEX  ENABLE
   )
/
ALTER TABLE  "EDITS" ADD FOREIGN KEY ("PUB_CODE")
      REFERENCES  "PUBLISHERS" ("PUB_CODE") ENABLE
/
Структура таблицы "Издания_авторы":
Oracle 11 SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE TABLE  "EDITS_AUTHORS" 
   (    "EDIT_CODE" CHAR(18) NOT NULL ENABLE, 
    "AUTHOR_CODE" NUMBER(4,0) NOT NULL ENABLE, 
    "PUB_CODE" NUMBER(4,0) NOT NULL ENABLE, 
    "AUTHOR_POSITION" NUMBER(1,0), 
    "FEE_PART" NUMBER(3,2), 
     PRIMARY KEY ("EDIT_CODE", "AUTHOR_CODE", "PUB_CODE")
  USING INDEX  ENABLE
   )
/
ALTER TABLE  "EDITS_AUTHORS" ADD FOREIGN KEY ("EDIT_CODE", "PUB_CODE")
      REFERENCES  "EDITS" ("EDIT_CODE", "PUB_CODE") ENABLE
/
ALTER TABLE  "EDITS_AUTHORS" ADD FOREIGN KEY ("AUTHOR_CODE")
      REFERENCES  "AUTHORS" ("AUTHOR_CODE") ENABLE
/
Ответ:
Сообщение от AGK
Можете выложить текст триггера, отвечающего за каскадное удаление?
триггер, отвечающий за каскадное удаление:
Oracle 11 SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
CREATE OR REPLACE TRIGGER findTieInfo
BEFORE DELETE ON edits
FOR EACH ROW
DECLARE
  
--l_author_list  VARCHAR2(4000);
--l_editor_list  VARCHAR2(4000);
v_login VARCHAR2(100);
v_action VARCHAR2(9);
 
  -- Курсор для поиска связанных авторов
  CURSOR c_edit_authors IS
    SELECT a.author_name,  a.author_surname,
      -- Собираем фио всех авторов через запятую
      LISTAGG(a.author_name||' '||a.author_surname) WITHIN GROUP(ORDER BY a.author_name) OVER() author_list
    FROM edits_authors ea, authors a
    WHERE ea.edit_code = :OLD.EDIT_CODE
    AND   a.author_code = ea.author_code
    FOR UPDATE OF ea.edit_code NOWAIT;
 
  -- Курсор для поиска связанных редакторов
  CURSOR c_edit_editors IS
    SELECT e.editor_name , e.editor_surname,
      -- Собираем фио всех редакторов через запятую
      LISTAGG(e.editor_name||' '||e.editor_surname) WITHIN GROUP(ORDER BY e.editor_name) OVER() editor_list
    FROM edits_editors ee, editors e
    WHERE ee.edit_code = :OLD.EDIT_CODE
    AND   e.editor_code = ee.editor_code
    FOR UPDATE OF ee.edit_code NOWAIT;
 
BEGIN
v_login := apex_util.get_username(apex_util.get_current_user_id);
 
  -- Ищем связанные записи в "Издания_авторы" добавляем в список и удаляем
  FOR r_row IN c_edit_authors LOOP
    -- Список авторов через запятую
    IF ChangeLogPack.l_author_list IS NULL THEN
      ChangeLogPack.l_author_list := r_row.author_list;
    END IF;  
    -- Удаляем найденного автора из оригинальной таблицы
    DELETE FROM edits_authors WHERE CURRENT OF c_edit_authors;
  END LOOP;             
 
 
  -- Ищем связанные записи в "Издания_редакторы" добавляем в список и удаляем  
  FOR r_row IN c_edit_editors LOOP
    -- Список авторов через запятую
    IF ChangeLogPack.l_editor_list IS NULL THEN
      ChangeLogPack.l_editor_list := r_row.editor_list;
    END IF;  
    -- Удаляем найденного редактора из оригинальной таблицы
    DELETE FROM edits_editors WHERE CURRENT OF c_edit_editors;
  END LOOP;             
END;
Вопрос: Триггер на запрет удаления

Люди, помогите написать триггер на mysql который при удалении записи из таблицы создаст копию этой записи в этой же таблице. Спасибо!
Ответ: В общем написал триггер, работает как надо. Вот если кому-то понадобиться:
Код SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DELIMITER //
 
CREATE TRIGGER contacts_before_delete
BEFORE DELETE
   ON contacts FOR EACH ROW
   
BEGIN
 
   IF OLD.contact_id = 150 THEN 
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'DELETE canceled'; 
    END IF;
   
END; //
 
DELIMITER ;
Вопрос: Запрос в Access выбрать из сводки три подразделения но с условием...

Имеется сводка в виде:

==========================
Склад1 Товар1 Остаток УсловиеЗапрета(Да)
Склад1 Товар1 Остаток УсловиеЗапрета(Нет)
Склад1 Товар1 Остаток УсловиеЗапрета(Нет)
Склад2 Товар2 Остаток УсловиеЗапрета(Нет)
Склад2 Товар2 Остаток УсловиеЗапрета(Нет)
Склад2 Товар2 Остаток УсловиеЗапрета(Нет)
Склад3 Товар3 Остаток УсловиеЗапрета(Нет)
Склад3 Товар3 Остаток УсловиеЗапрета(Нет)
Склад3 Товар3 Остаток УсловиеЗапрета(Нет)
==========================

Как в запросе в Access выбрать из сводки три склада но с условием только Склада1 по конкретному товару, т.е. мы должны видеть след.выборку

==========================
Склад1 Склад2 Склад3
Товар2 Остаток Остаток Остаток
==========================

т.е. товар1 у нас отпадает в связи с запретом по первому складу, не учитывая условий запрета по конкретному складу.


P.S. Перекрестный запрос я сделал, не могу догнать куда вписать условие только по первому складу.
Ответ:
Истина где-то рядом
Перекрестный запрос я сделал, не могу догнать куда вписать условие только по первому складу.
Надо построить запрос, который отсеивает товары по условию запрета, и уже на его основе строить перекрёстный запрос.

Модератор: Тема перенесена из форума "Microsoft Office".
Вопрос: Запрет на удаление столбца(колонки) в форме.

Добрый день.
Проблема собственно в шапке. Необходимо запретить пользователям возможность удаления столбца в подчиненной форме. Редактирование/ добавление/ изменение записей отключено. Доступ к контекстному меню убрал, но если выделить столбец и нажать del, столбец удаляется. Можно поставить перехват действий клавиши, но наверное есть какой-то более простой способ о котором пока не знаю!
Заранее спасибо за совет.
Ответ:
trexmernii
Добрый день.
Проблема собственно в шапке. Необходимо запретить пользователям возможность удаления столбца в подчиненной форме. Редактирование/ добавление/ изменение записей отключено. Доступ к контекстному меню убрал, но если выделить столбец и нажать del, столбец удаляется. Можно поставить перехват действий клавиши, но наверное есть какой-то более простой способ о котором пока не знаю!
Заранее спасибо за совет.


Какой еще запрет на удаление поле у вас что юзера схему правят через полный доступ к таблицам пипец....
Вопрос: Запрет подключения к серверу ORACLE с определённого компьютера

День добрый. Скажите пожалуйста, есть ли возможность в оракле установить где-нибудь (например, в триггере на логон) запрет на подключение по какому-нибудь условию (например, по имени машины)?
Ответ:
ProRockX
День добрый. Скажите пожалуйста, есть ли возможность в оракле установить где-нибудь (например, в триггере на логон) запрет на подключение по какому-нибудь условию (например, по имени машины)?


не?
Вопрос: Быстрое удаление

Нужно максимально быстро в скрипте удалить записи по условию
DELETE FROM
  my_table
WHERE
  my_field1 IS NULL OR
  my_field2 IS NULL

Поля my_field1 -INTEGER, my_field2 - SMALLINT. Данный запрос удалит 20%-30% записей в таблице. Всего в таблице записей - сотни тысяч. С вероятностью 99% второе условие лишнее и эти два поля либо оба NULL, либо оба не NULL

Вопросы.

1. Условие по одному полю ускорит удаление?
2. Индекс по my_field1, my_field2 как-то изменит время удаления?
3. Деактивация остальных индексов в таблице повлияет на скорость?
4. На эту таблицу ссылается несколько внешних ключей с условиями ON DELETE CASCADE и ON DELETE SET NULL. Отработка этих условий самостоятельно, удаление этих ключей и последующее восстановление ускорит общий процесс?
5. Может еще какие условия забыл?
6. Про отключение триггеров помню

С уважением, Vasilisk
Ответ:
_Vasilisk_
pastor
3. Повлияет, но потребует монопольного подключения к БД
Это есть
pastor
4. Нет. Отличаются только крыжиком системный/пользовательский.
pastor
Нужно сначала удалять из зависимых таблиц delete where (условие по мастеру)
Эти два условия не противоречат друг другу?


Нисколько.

При удалении по триггеру/каскаду (неважно, системному или пользовательскому) происходит попеременное дерганье НА КАЖДОЕ ВХОЖДЕНИЕ мастера (поиск/чтение) слейва, индекса слейва. В самом печальном случае читается/записывается по странице данных и странице каждого индекса. На каждую запись. Кол-во задействованных страниц (Кол-во записей мастера) * (кол-во индексов слейва). (Стотыщ записей) * (3 индекса) = Триста тыщ страничных операций. + операции в мастере. И все вперемешку, без попадания в страничный и файловый/дисковый кэш.

При удалении порцией - максимальное кол-во изменяемых страниц не может превысить число страниц (данных и индексов) в слейве.
на (стотыщ записей) / (16к / размер записи 100) * 3 индекса = 62,5 * 3 = 187,5 страничных операций.

Подсчеты оценочные, с точностью до порядка.
Вопрос: Запрет удаления по условию

Подскажите пожалуйста, как в табличной форме запретить удалять записи при наличии значение истина в поле?

Добавлено через 7 минут
SQL
1
2
3
4
5
6
Private Sub Form_Delete(Cancel AS INTEGER)
    IF Me.Поле = TRUE THEN
        MsgBox "удалить нельзя"
        Cancel =  TRUE 
    END IF
END Sub
Добавлено через 21 секунду
Так правильно?
Ответ: Вполне.
Вопрос: Запрет на удаление, доступ к записи

Добрый день.

У меня есть БД1 в локальной сети, в которой хранятся таблица и форма для ее изменения. Есть БД2 в локальной сети, в которой по запросу Кнопки1 открывается Форма из БД1, по кнопке2 открывается таблица из БД2.
Вопрос: при нажатии на кнопку2 - откроется таблица, как мне запретить удаление содержимого ячеек в этой таблице (которая откроется в БД2) другим пользователям? Но оставить доступ на добавление записей через форму.
Ответ:
usernameMax
как мне запретить удаление содержимого ячеек в этой таблице (которая откроется в БД2) другим пользователям?
Т.е. таблица одна и та же? У формы есть свойство "Блокировка записей", попробуйте указать "Все записи".

usernameMax
Но оставить доступ на добавление записей через форму.
Если только добавление, то, опять же, в свойствах "Разрешить удаление" и "Разрешить изменение" - НЕТ. Ну или "Ввод данных" - ДА, если существующие записи не интересуют.
Вопрос: Удаление по условию записей из запроса на объединение

Доброе утро, можно ли из запроса на объединение производить удаление записей по условию. Удаление записей не зацепит сам источник данных на основании которого делался запрос на объединение?
Ответ: Открыть accdb не могу. Как я понял, на форме выбираются значения нескольких полей а потом по кнопке запрос с параметрами из этих полей должен экспортироваться в эксель.
Тогда внутри запроса в условиях надо писать Forms!Форма!Поле. А кнопка делает только экспорт запроса. Никакими параметрами она управлять не будет
Вопрос: Триггер добавление\удаление данных на основании условия

Прошу помощи в, казалось бы, такой просто штуке как вставка данных в другую таблицу на основании какого-то условия.
Итак суть:
Есть две таблицы:
Люди:
CREATE TABLE "public"."persons" ( 
	"id" Integer DEFAULT nextval('person_id_seq'::regclass) NOT NULL,
	"surname" Character Varying( 100 ) NOT NULL,
	"name" Character Varying( 100 ) NOT NULL,
	"patronymic" Character Varying( 100 ),
	"date_birth" Date NOT NULL,
	"place_birth" Character Varying( 1000 ) NOT NULL,
	"parent_id" Integer,
	"surnamepat" Character Varying,
	"surnamepat_short" Character Varying,
	PRIMARY KEY ( "id" ) );

История законных представителей:
CREATE TABLE "public"."history_legal_representatives" ( 
	"id" Integer DEFAULT nextval('history_legal_representative_id_seq'::regclass) NOT NULL,
	"person_id" Integer NOT NULL,
	"person_parent_id" Integer NOT NULL,
	"modified" Date DEFAULT ('now'::text)::date,
	PRIMARY KEY ( "id" ) );


Где соответственно поля:
"person_id" - Человек (в таблице persons - id)
"person_parent_id" - Законный представитель (в таблице persons - parent_id)


Что пытаюсь сделать:
При добавлении в таблицу persons записи, у которой parent_id - не указан, просто добавляем эту запись, если же parent_id указано, то в таблицу history_legal_representatives добавляем запись - person_id:= persons.id и person_parent_id:=persons.parent_id.
При редактировании записей в таблице persons, если значение parent_id становится NULL удалить такую пару из history_legal_representatives. (если такая логина неверна, прошу указать почему\как правильнее)

Сам код:
Добавление
CREATE TRIGGER addrep BEFORE INSERT ON "public"."persons" FOR EACH ROW EXECUTE PROCEDURE addrepresentative()

CREATE OR REPLACE FUNCTION public.addrepresentative()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
BEGIN
	if NEW.parent_id != NULL then
	insert into history_legal_representatives (person_id, person_parent_id) 
	values (NEW.id, NEW.parent_id);
	end if;
	RETURN NEW;
END;
$function$


Удаление
CREATE TRIGGER delrep BEFORE UPDATE ON "public"."persons" FOR EACH ROW EXECUTE PROCEDURE delrepresentative()

CREATE OR REPLACE FUNCTION public.delrepresentative()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
BEGIN
	if NEW.parend_id = null then
	delete from history_legal_representatives where id = NEW.id;
	end if;
	RETURN NEW;
END;
$function$


Сильно прошу не пинать, в sql не особо силен, хочу сделать это для того, чтобы в вебе это не мудрить.
Ответ: Нашел еще ошибку :( неправильный id брал при удалении - нужен был person_id
Можно закрывать тему.