Невозможно изменить тип столбца с даты на целое число - PullRequest
1 голос
/ 10 июля 2020

В настоящее время я пытаюсь использовать найденное решение здесь , но, похоже, я не могу изменить тип столбца пользователей с date на integer.

Когда я пытаюсь:

ALTER TABLE users ALTER COLUMN password_reset_expires TYPE integer;

Я получаю эту ошибку:

ERROR:  column "password_reset_expires" cannot be cast automatically to type integer
HINT:  You might need to specify "USING password_reset_expires::integer".

И когда я пытаюсь:

ALTER TABLE users ALTER COLUMN password_reset_expires TYPE integer
USING (password_reset_expires::integer);

Ошибка сообщает мне:

ERROR:  cannot cast type date to integer
LINE 1: ...expires TYPE integer USING (password_reset_expires::integer)...

Определение моей таблицы:

                                            Table "public.users"
         Column         |          Type          | Collation | Nullable |              Default
------------------------+------------------------+-----------+----------+-----------------------------------
 id                     | bigint                 |           | not null | nextval('users_id_seq'::regclass)
 name                   | character varying(20)  |           | not null |
 email                  | character varying(100) |           | not null |
 password               | character varying(500) |           | not null |
 password_changed_at    | date                   |           |          |
 password_reset_token   | character varying(300) |           |          |
 password_reset_expires | date                   |           |          |
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "tokens" CONSTRAINT "tokens_token_pk_fkey" FOREIGN KEY (fk_users_id) REFERENCES users(id)

Вот один из моих пользовательских объектов:

{
  id: '59',
  name: 'visitor',
  email: 'visitor',
  password: '$2b$10$0UGgdRUlXFYeQfk5Nv/vXe9khdzyyOqsTiFGyNXLfEDuOFAt0xc1G',
  password_changed_at: null,
  password_reset_token: null,
  password_reset_expires: null
}

1 Ответ

1 голос
/ 10 июля 2020

Обычно используйте стандартную функцию SQL EXTRACT(). Ваш комментарий :

То, что я хочу сохранить в password_reset_expires, а password_changed_at - это число вроде этого 1594329364292

... указывает вы хотите сохранить количество миллисекунд с эпохи UNIX 1970-01-01 00: 00: 00 как целочисленное значение. Но это выходит за пределы диапазона типа integer (подписанный int4), который позволяет использовать числа до 2 ^ 31-1 = 2147483647 . На момент написания уже прошло 1594335691272 миллисекунды с эпохи.

Либо сохранить секунды в столбце integer:

ALTER TABLE users ALTER COLUMN password_reset_expires TYPE integer
USING (EXTRACT(EPOCH FROM password_reset_expires)::int);

Или сохранить миллисекунды в столбце bigint (подписанный int8, позволяет до 2 ^ 63-1 = 9223372036854775807 ):

ALTER TABLE users ALTER COLUMN password_reset_expires TYPE bigint -- !
USING (EXTRACT(EPOCH FROM password_reset_expires)::bigint * 1000);

EXTRACT(EPOCH FROM ...) возвращает, согласно руководству :

Для значений timestamp with time zone количество секунд с 1970-01-01 00:00:00 UT C (может быть отрицательным); для значений date и timestamp количество секунд с 1970-01-01 00:00:00 по местному времени; для значений interval общее количество секунд в интервале

Поскольку в этом случае источником является date, дробных секунд быть не может, и мы можем просто умножить на 1000, чтобы получить число миллисекунд.

Опять же, если не может быть миллисекунд, зачем сохранять количество миллисекунд для начала?

Что еще более важно, почему бы не сохранить date? Если значение на самом деле представляет дату, тип данных date почти наверняка является лучшим вариантом.

...