ORA-00933:同时删除两个表时SQL命令未正确结束

Ren*_*uza 1 oracle plsql sql-delete

我试图删除两个相关表中的数据 - 表中的主键和表中的users外键login- 但我收到错误PL/SQL: ORA-00933: SQL command not properly ended.

创建表users和主键:

/* table user*/
create table users (id_user number(10) not null, 
                    name_user varchar(30) not null);
/* primary key */
alter table users add constraint user_pk primary key (id_user);
Run Code Online (Sandbox Code Playgroud)

创建表login和主键以及外键:

/* table login*/
create table login (id_login number(10) not null, 
                    id_user_login number(10) not null, 
                    email_login varchar(20) not null,
                    password_login varchar(20) not null);
/* primary key */
alter table login add constraint login_pk primary key (id_login);

/* foreign key reference to user*/
alter table login add constraint login_fk_user foreign key (id_user_login)
references users(id_user) on delete cascade;
Run Code Online (Sandbox Code Playgroud)

使用table users/ 创建会话的过程login,其工作原理:

PROCEDURE create_user_session( p_name   IN VARCHAR2,
                               p_email  IN VARCHAR2,
                               p_pass   IN VARCHAR2,
                               p_error  OUT NUMBER,
                               p_msg_error OUT VARCHAR2)
  IS
  BEGIN
    p_error := 0;
    INSERT ALL

    INTO users (id_user, name_user) VALUES(seq_user.NEXTVAL,p_name)

    INTO login(id_login, id_user_login, email_login, pass_login)
    VALUES(seq_login.NEXTVAL, seq_user.CURRVAL, p_email, p_pass)

    SELECT * FROM DUAL COMMIT;
  EXCEPTION
  WHEN OTHERS THEN
    p_error     := 1;
    p_msg_error := 'Error!'||SQLERRM;
  END create_user_session;
Run Code Online (Sandbox Code Playgroud)

现在我想删除此会话,但我PL/SQL: ORA-00933: SQL command not properly ended从此过程中得到错误:

PROCEDURE delete_user_session(
    p_id_user IN NUMBER,
    p_error OUT NUMBER,
    p_msg_error OUT VARCHAR2)
IS
BEGIN
  p_error := 0;
  DELETE FROM users, login USING users
  INNER JOIN login WHERE users.id_user = p_id_user
  AND login.id_user_login  = p_id_user;
  COMMIT;
EXCEPTION
WHEN OTHERS THEN
  p_error     := 1;
  p_msg_error := 'Error!'||SQLERRM;
END delete_user_session;
Run Code Online (Sandbox Code Playgroud)

我有来自SQL开发人员的这个图像来显示错误(如果你看不到图像s,,DELETE FROM users, login ...则在in中出现红色波浪线下划线):

在此输入图像描述

我究竟做错了什么?

Ale*_*ole 6

您不能在一个语句中从两个表中删除 - 没有删除等效的insert all.(除非您具有级联删除的约束或手动执行此操作的触发器).文档显示您的语法无效,因为没有指定多个表的路径.

您需要有两个delete语句,首先从子表中删除记录:

  DELETE FROM login 
  WHERE login.id_user_login = p_id_user;
  DELETE FROM users
  WHERE users.id_user = p_id_user;
Run Code Online (Sandbox Code Playgroud)

可以将外键约束更改为delete cascade:

alter table login add constraint login_fk_user foreign key (id_user_login)
references users(id_user) on delete cascade;
Run Code Online (Sandbox Code Playgroud)

...这意味着你只需要从users表中明确删除; 但这可能实际上并不是你想要的,因为它删除了一个级别的验证 - 你可能想要防止父键在有子级时被意外删除.发出两次删除并不会在这里造成伤害.

顺便提一下,您的第一个程序不是提交,这可能是您所期望的.在这一行:

    ...
    SELECT * FROM DUAL COMMIT;
Run Code Online (Sandbox Code Playgroud)

... COMMIT被解释为DUAL表的别名,而不是单独的命令.之后你需要一个分号DUAL,最好是一个新的代号COMMIT;.但通常认为最好不要在过程中提交,并让顶级调用者决定是提交还是回滚以保持数据完整性.