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