Написать код функции в PostgreSQL без долларового цитирования (`$$`) можно, используя обычные одинарные кавычки. В этом случае все кавычки внутри кода функции нужно **удваивать** (`''`), чтобы база понимала, что это текст внутри текста.
Вот полный проект с нуля в этом стиле.
### Шаг 1: Создание таблиц
Выполните в Query Tool:
```sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username TEXT NOT NULL,
email TEXT
);
CREATE TABLE users_log (
log_id SERIAL PRIMARY KEY,
user_id INT,
operation TEXT,
changed_by TEXT,
changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
data_json JSONB
);
```
### Шаг 2: Создание функции и триггера (без знака $)
Здесь вместо `$$` используются обычные кавычки `'`, а внутри кода все текстовые значения пишутся с двойными кавычками `''`.
```sql
CREATE OR REPLACE FUNCTION log_changes()
RETURNS TRIGGER AS
'
BEGIN
IF (TG_OP = ''DELETE'') THEN
INSERT INTO users_log (user_id, operation, changed_by, data_json)
VALUES (OLD.id, TG_OP, current_user, to_jsonb(OLD));
ELSE
INSERT INTO users_log (user_id, operation, changed_by, data_json)
VALUES (NEW.id, TG_OP, current_user, to_jsonb(NEW));
END IF;
PERFORM pg_notify(''audit_chan'', ''Изменение: '' || TG_OP);
IF (TG_OP = ''DELETE'') THEN RETURN OLD; ELSE RETURN NEW; END IF;
END;
'
LANGUAGE plpgsql;
CREATE TRIGGER trg_users_audit
AFTER INSERT OR UPDATE OR DELETE ON users
FOR EACH ROW EXECUTE FUNCTION log_changes();
```
### Шаг 3: Настройка уведомлений
Выполните, чтобы начать слушать сигналы:
```sql
LISTEN audit_chan;
```
### Шаг 4: Проверка для экзамена
**1. Добавление записи:**
```sql
INSERT INTO users (username, email) VALUES ('student', 'test@test.ru');
```
**2. Просмотр уведомления:**
Нажмите на вкладку **Messages** внизу. Вы увидите строку с текстом `Изменение: INSERT`.
**3. Отчет за месяц:**
```sql
SELECT * FROM users_log
WHERE changed_at >= NOW() - INTERVAL '1 month'
ORDER BY changed_at DESC;
```
---
### Ответы на теорию (кратко):
1. **Аудит:** Это фиксация истории изменений. Настроен через триггер и таблицу `users_log`.
2. **Уведомления:** Использован механизм `NOTIFY`. Он передает сигнал о событии внешним программам (аналог Database Mail).
3. **Защита:** Реализуется через роли доступа (GRANT/REVOKE) и политики безопасности строк (RLS).
4. **Почему без $$?** Использовано стандартное строковое цитирование. Все внутренние кавычки в коде пришлось экранировать (писать по две), чтобы база не приняла их за конец функции.