#sql #oracle
Вопрос:
Как я могу добавить дату «сейчас» в столбец? Я хочу реализовать следующий сценарий: если я вставлю строку сегодня, столбец даты будет иметь значение 25/10/2021, и если завтра я выполню инструкцию SELECT, я хочу, чтобы этот столбец был обновлен со значением 26/10/2021 и так далее. Есть ли способ обновлять столбец без того, чтобы я что-либо делал вручную? Спасибо.
Последующее редактирование: Я хочу использовать этот столбец для ПЕРИОДА во временной таблице. Пример: ПЕРИОД ДЛЯ example_period(some_date, now_date)
Комментарии:
1. Но как говорит Литтлфут в своем ответе. Если он должен отображать текущую дату при каждом запуске запроса, почему бы вам просто не отобразить
sysdate
ее (илиtrunc(sysdate)
только для даты)? Зачем хранить значение, которое должно меняться каждый день в полночь? Это, кажется, не имеет смысла.2. Я знаю, но это та просьба, которую я получил. Допустим, у меня есть запись: Имя: зарплата: 123 Дата начала: 10-10-2020 Дата окончания: время от времени я хочу обновить зарплату таким образом, чтобы у меня было 2 записи для одного и того же человека: Имя: Зарплата: 123 Дата начала: 10-10-2020 Дата окончания: 25-10-2021; Имя: Зарплата: 123 Дата начала: 25-10-2021 Дата окончания: сейчас
3. Затем напишите представление или добавьте вычисляемый столбец, который использует
sysdate
.4. Я отредактировал свою предыдущую одежду. Что такое вычисляемый столбец? Можете ли вы привести мне пример?
5. Хорошо, с вашим измененным комментарием это звучит иначе, чем то, что вы говорили до сих пор. Вы хотите разделить ряд на две части? В какой ситуации?
Ответ №1:
В комментариях к вашему запросу вы коренным образом изменили свой запрос.
Одна проблема: у вас есть открытый диапазон дат с датой начала и датой окончания. Но при отображении этого вы хотите заменить «без конца» текущей датой. Обычно это делается путем сохранения значения null (без значения) для даты. В запросе, который вы затем можете использовать COALESCE
, чтобы заменить его текущей датой:
SELECT
empno,
salary,
start_date AS first_day,
COALESCE(end_date, TRUNC(SYSDATE)) AS last_day
FROM salaries;
И для удобства вы можете сделать это представление:
CREATE VIEW v_salaries AS SELECT <above query>
Другая проблема заключается в том, что вы хотите, чтобы это значение null менялось при добавлении новой информации о зарплате.
Вручную вы бы просто
INSERT INTO salaries (empno, salary, start_date, end_date)
VALUES(50, 1200, TRUNC(SYDATE), NULL);
UPDATE salaries SET end_date = TRUNC(SYSDATE) - 1
WHERE empno = 50 AND end_date IS NULL;
Если вы хотите, чтобы это обновление происходило автоматически, есть в основном два варианта:
- напишите процедуру для новой зарплаты, которая выполняет вставку и обновление
- напишите триггер для выполнения обновления
Ответ №2:
В этом нет никакого смысла. Это как если бы вы просто
select empno, ename,
sysdate --> this
from employees
каждый раз.
SELECT
не будет обновлять значения столбцов, поэтому … зачем вам вообще хранить такую дату, если вы хотите, чтобы она была синхронизирована sysdate
?
Но если вы хотите, чтобы Oracle вставляла sysdate
в этот столбец значение по умолчанию, вы должны создать столбец как таковой, например
SQL> create table test
2 (id number,
3 datum date default sysdate
4 );
Table created.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> insert into test (id) values (1);
1 row created.
SQL> select * from test;
ID DATUM
---------- -------------------
1 25.10.2021 14:05:02
SQL>
Но, это останется тем же «навсегда», если вы на самом деле update
не оцените его ценность.
Комментарии:
1. Я хочу использовать эту колонку в течение определенного ПЕРИОДА. Например: ПЕРИОД ДЛЯ example_period(some_date, now_date)
2. Для чего нужен ПЕРИОД? Как бы вы его использовали? Что такое SOME_DATE?
3. ПЕРИОД ДЛЯ оператора используется для временных таблиц. some_date-это просто прошлая дата, которую я установлю.
4. Допустим, у меня есть запись: Имя: зарплата: 123 Дата начала: 10-10-2020 Дата окончания: время от времени я хочу обновить зарплату таким образом, чтобы у меня было 2 записи для одного и того же человека: Имя: Зарплата: 123 Дата начала: 10-10-2020 Дата окончания: 25-10-2021; Имя: Зарплата: 123 Дата начала: 25-10-2021 Дата окончания: сейчас
5. Ага. Речь идет о временной действительности ( oracle-base.com/articles/12c/… ). То, как вы описали это в своем последнем комментарии, я не думаю, что его следует использовать таким образом. Вам придется а) обновить существующую строку, чтобы вставить значение END_DATE, б) вставить новую строку, в которой отображается новая зарплата человека, которая действительна с «сейчас» и далее.
Ответ №3:
Добавьте триггер, который заполняет столбец sysdate :
create or replace TRIGGER TRG_FILL_DATE
BEFORE INSERT ON MY_TABLE
FOR EACH ROW
WHEN (NEW.MY_DATE_COLUMN IS NULL)
BEGIN
SELECT sysdate INTO :NEW.MY_DATE_COLUMN FROM DUAL;
END;
Или, как предлагается, используйте «sysdate ПО УМОЛЧАНИЮ» в своей колонке.
Комментарии:
1. Ммм … нет, не используйте спусковой крючок для такой цели. Вместо этого установите значение столбца по умолчанию .
2. Действительно. Проще добавить значение по умолчанию.
3. Не только проще; база данных пострадала бы, если бы ей пришлось запускать этот триггер в операции массовой вставки, которая вставляет 10 миллионов строк, столбец my_date_column которых пуст.
Ответ №4:
Вы можете использовать сгенерированный столбец:
CREATE TABLE salaries (
id NUMBER(10,0)
GENERATED ALWAYS AS IDENTITY
CONSTRAINT salaries__id__pk PRIMARY KEY,
emp_id CONSTRAINT salaries__emp_id__fk REFERENCES employees (id)
NOT NULL,
salary NUMBER(12,2)
NOT NULL,
start_date DATE
NOT NULL,
end_date DATE
NULL,
assumed_end_date DATE
GENERATED ALWAYS AS (date_or_now(end_date))
NOT NULL
);
и создайте DETERMINISTIC
функцию (слегка злоупотребляя тем, как она должна использоваться):
CREATE FUNCTION date_or_now (dt IN DATE) RETURN DATE DETERMINISTIC
IS
BEGIN
RETURN COALESCE(dt, SYSDATE);
END;
/
Тогда, если вы:
INSERT INTO salaries (emp_id, salary, start_date)
VALUES (1, 123, DATE '2021-01-01');
Затем:
SELECT *
FROM salaries;
На выходе получается:
ID EMP_ID зарплата ДАТА НАЧАЛА ДАТА ОКОНЧАНИЯ ПРЕДПОЛАГАЕМАЯ ДАТА 1 1 123 2021-01-01 00:00:00 2021-10-25 13:28:08
Тогда, если вы это сделаете:
UPDATE salaries
SET END_DATE = DATE '2021-10-01'
WHERE id = 1;
INSERT INTO salaries (emp_id, salary, start_date)
VALUES (1, 234, DATE '2021-10-01');
Затем:
SELECT *
FROM salaries;
На выходе получается:
ID EMP_ID зарплата ДАТА НАЧАЛА ДАТА ОКОНЧАНИЯ ПРЕДПОЛАГАЕМАЯ ДАТА 1 1 123 2021-01-01 00:00:00 2021-10-01 00:00:00 2021-10-01 00:00:00 2 1 234 2021-10-01 00:00:00 2021-10-25 13:28:08
бд<>скрипка <>здесь