Babelfish: запрос UPDATE с JOIN

У меня есть следующие образцы данных:

      create table employee (id int,emp_name varchar(50),project_name varchar(50)); 
insert into employee(id,emp_name) values(1,'Smith');
insert into employee(id,emp_name) values(2,'Jill');
insert into employee(id,emp_name) values(3,'Hana');

create table employee_project (emp_id int,project_id int); 
insert into employee_project(emp_id,project_id) values(1,101);
insert into employee_project(emp_id,project_id) values(2,201);
insert into employee_project(emp_id,project_id) values(3,301);

create table project (id int,pro_name varchar(50)); 
insert into project(id,pro_name) values(101,'School');
insert into project(id,pro_name) values(201,'Tax');
insert into project(id,pro_name) values(301,'Road');

мне нужно обновить таблицуemployeeстолбецproject_name.

Обновление запросов :

Попытка 1: Не удалось — Ошибка: отношение «e» не существует.

      update e 
set project_name = p.pro_name 
from employee e
inner join employee_project ep on ep.emp_id = e.id
inner join project p on p.id = ep.project_id;

Попытка 2: Не удалось — Ошибка: отсутствует запись предложения FROM для таблицы «p».

      update employee 
set project_name = p.pro_name 
from employee e
inner join employee_project ep on ep.emp_id = e.id
inner join project p on p.id = ep.project_id;

Попробуйте 3: работает

      update employee 
set project_name = p.pro_name 
from  employee_project ep 
inner join project p on p.id = ep.project_id
WHERE ep.emp_id = employee.id;

Попытка 3 работает нормально, но я не уверен в стандарте SQL ANSI, а также в том, как она будет работать для разных соединений (ЛЕВО, ПРАВО), когда базовая таблица имеет несколько разных объединений.

Примечание. Я выполняю эти запросы из SQL Server Management Studio.

2 ответа

Ошибки, с которыми вы столкнулись, возникают в Babelfish версии 2.3.x и более ранних версиях. В версии 2.4.0 и более поздних версиях они были исправлены.

SQL Server принимает специальный синтаксис для UPDATE с JOIN, которого нет в стандарте ISO SQL.

Этот синтаксис быстрее официальных, в которых используются операторы IN, ALL, ANY или EXISTS, которые сложно написать...

Таким образом, этот синтаксис недоступен в некоторых других СУБД!

ВНИМАНИЕ : в случае UPDATE и с учетом задействованной мощности обновление может быть неоднозначным, поскольку оно является произвольным. Действительно, если столбцы, содержащиеся в обновляемых выражениях значений, происходят из объединенных таблиц, мощность которых больше 1 для каждой обновляемой строки, то назначенным значением будет любое из значений, полученных в результате объединения!

В качестве примера в моей следующей книге по SQL я привожу следующий SQL-скрипт:

      CREATE TABLE dbo.T_PERSONNE_PHYSIQUE_PSP
(PSP_ID               INT PRIMARY KEY,
 PSP_NOM_NAISSANCE    VARCHAR(64) NOT NULL,
 PSP_NOM_MARITAL      VARCHAR(64),
 PSP_PRENOM_USUEL     VARCHAR(32),
 PSP_DATE_NAISSANCE   DATE NOT NULL);

CREATE TABLE dbo.T_PRENOM_PRN
(PRN_ID      INT PRIMARY KEY,
 PRN_PRENOM  VARCHAR(32) NOT NULL UNIQUE);

CREATE TABLE dbo.T_PERSONNE_PHYSIQUE_PRENOM_PPP
(PPP_ID      INT IDENTITY PRIMARY KEY,
 PSP_ID      INT NOT NULL REFERENCES dbo.T_PERSONNE_PHYSIQUE_PSP (PSP_ID),
 PRN_ID      INT NOT NULL REFERENCES dbo.T_PRENOM_PRN (PRN_ID),
 PPP_ORDRE   TINYINT NOT NULL,
 UNIQUE (PSP_ID, PPP_ORDRE));

INSERT INTO dbo.T_PRENOM_PRN VALUES 
(1, 'Georges'), (2, 'Charles'), (3, 'André'), (4, 'Jean'), 
(5, 'Marie'), (6, 'Joseph'), (7, 'Benjamin'), (8, 'Raymond'),
(9, 'Marc'), (10, 'Paul'), (11, 'Jacques'), (12, 'Simone');

INSERT INTO dbo.T_PERSONNE_PHYSIQUE_PSP VALUES
(99, 'DE GAULLE', NULL, NULL, '1890-11-22'), -- Charles André Joseph Marie
(98, 'CLEMENCEAU', NULL, NULL, '1841-09-28'), -- Benjamin Georges
(97, 'POMPIDOU', NULL, NULL, '1911-07-05'); --Georges Jean-Raymond

INSERT INTO dbo.T_PERSONNE_PHYSIQUE_PRENOM_PPP VALUES
(99, 2, 1), (99, 3, 2),  (99, 6, 3), (99, 5, 4),
(98, 7, 1), (98, 1, 2),
(97, 1, 1), (97, 4, 2), (97, 8, 3);

UPDATE T
SET    PSP_PRENOM_USUEL = P.PRN_PRENOM
FROM   dbo.T_PERSONNE_PHYSIQUE_PSP AS T 
       JOIN dbo.T_PERSONNE_PHYSIQUE_PRENOM_PPP AS PP
          ON T.PSP_ID = PP.PSP_ID
       JOIN dbo.T_PRENOM_PRN AS P
          ON PP.PRN_ID = P.PRN_ID;

Результатом будет:

      PSP_ID      PSP_NOM_NAISSANCE   PSP_PRENOM_USUEL
----------- ------------------- ----------------
97          POMPIDOU            Georges
98          CLEMENCEAU          Benjamin
99          DE GAULLE           Charles

Если я добавлю следующий индекс:

      CREATE INDEX X_PPP_PRN_PSP 
   ON T_PERSONNE_PHYSIQUE_PRENOM_PPP (PSP_ID, PRN_ID);

Результат сейчас:

      PSP_ID      PSP_NOM_NAISSANCE   PSP_PRENOM_USUEL
----------- ------------------- ------------------
97          POMPIDOU            Georges
98          CLEMENCEAU          Georges
99          DE GAULLE           Charles
Другие вопросы по тегам