«Существует столбец с именем ... на него нельзя ссылаться из этой части запроса». Как это исправить?

Есть простая таблица со столбцами a,b,c,d. Я хочу, чтобы значение в d было a+b, если c>0, и a-b, если c<=0. Как я могу это сделать?

Я пробовал этот код, и он не работает. Как я могу динамически вставлять данные в таблицу?

INSERT INTO my_table VALUES(1,2,3, 
CASE
    WHEN c<0
    THEN a+b
    ELSE a-b
END
)

Скажите, пожалуйста, зачем вам это нужно? Возможно, лучше изменить дизайн таблицы. Также может быть лучше сделать это на языке программирования, а не на SQL.

Schwern 15.01.2023 04:37

У меня есть задача вставить такие данные, и я просто сделал этот пример, чтобы понять, как справиться с этой проблемой. Как я могу сделать это, например, с помощью python?

Роман Свирид 15.01.2023 04:42
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
2
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Мне нужно значение в D (a+b), если C>0, и (a-b), если C<=0. Как я могу это сделать?

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

insert into my_table(a, b, c, d)
  values(
    $1, $2, $3,
    case
    when $3 > 0 then $1 + $2
    else $1 - $2
  )

Вы также можете написать функцию.

--  I want value in D (a+b) if C>0 and (a-b) if C<=0.
create function my_insert(a int, b int, c int)
returns void
language plpgsql
as $$
declare d integer;
begin
  case
  when c > 0 then d = a + b;
  else d = a - b;
  end case;

  insert into my_table ("a", "b", "c", "d") values (a, b, c, d);
end;
$$

select my_insert(1, 2, 3);

Демонстрация.

Работая с литеральными значениями, вы можете добиться того же с помощью подзапроса:

INSERT INTO my_table (a,b,c,d) 
SELECT *, CASE WHEN c<0 THEN a+b ELSE a-b END AS d
FROM (
   VALUES
     (3,2, 1)  -- input values here, once
   , (3,2,-1)  -- multiple rows if need be
   ) sub(a,b,c);

Это работает без явного приведения типов для базовых типов, таких как integer или text, поскольку предполагаемые типы по умолчанию для литералов совпадают. Вам может понадобиться явное приведение типов данных для других типов данных в отдельном выражении VALUES. Видеть:

Более того, избегайте этой проблемы, не сохраняя избыточные данные в таблице с самого начала.

CREATE TABLE my_table (
  a int
, b int
, c int
--  NO d; will be computed on the fly
);

INSERT возвращается к истокам:

INSERT INTO my_table (a,b,c) VALUES
  (3,2, 1)
, (3,2, 0)
, (3,2,-1)
;

Дополнительный столбец d можно дешево вычислить на лету. Обычно намного дешевле, чем чтение большего количества страниц данных из-за увеличения объема памяти:

SELECT *, CASE WHEN c<0 THEN a+b ELSE a-b END AS d
FROM   my_table;

Вы можете сохранить логику в VIEW:

CREATE VIEW my_view AS
SELECT *, CASE WHEN c<0 THEN a+b ELSE a-b END AS d
FROM   my_table;

SELECT * FROM my_view;

Если вам определенно нужно сохранить вычисленное значение (например, когда вычисления относительно дороги или вы делаете другие вещи со столбцом), используйте сгенерированный столбец STORED (Postgres 12+):

ALTER TABLE my_table
ADD column d int GENERATED ALWAYS AS (CASE WHEN c<0 THEN a+b ELSE a-b END) STORED;

SELECT * my_table;

рабочий пример

Видеть:

Спасибо, что предложили сгенерированный столбец! Но в моем проекте у меня была проблема с этим: мне нужен сгенерированный столбец для ссылки на 2 других сгенерированных столбца, и, к сожалению, это вызывает ошибку.

Роман Свирид 15.01.2023 09:16

@РоманСвирид: Понятно. Всегда есть исключения из правил ... Также вверху добавлено чистое решение SQL DML.

Erwin Brandstetter 15.01.2023 09:22

Другие вопросы по теме