【问题标题】:List of Record type matching issue Oracle记录类型匹配问题 Oracle 列表
【发布时间】:2021-02-11 18:57:13
【问题描述】:

我想检查all_workspace 表中是否没有工作区,然后创建新工作区。
我的要求是如果p_workspacev_workspace 的值列表不匹配,那么它应该创建一个新的。

DECLARE
p_workspace VARCHAR2(100):='WS-38515';
TYPE t_ws IS TABLE OF VARCHAR2(30);
v_workspace t_ws := t_ws();
Begin
  execute immediate '
    SELECT
    DISTINCT WORKSPACE 
    FROM WMSYS.all_workspaces 
    '
    BULK COLLECT INTO v_workspace;
      FOR i IN v_workspace.first..v_workspace.last LOOP
        IF v_workspace(i) <> p_workspace THEN
           dbms_wm.CreateWorkspace(p_workspace,isrefreshed=>TRUE);
        END IF;
      END LOOP;   
        EXCEPTION
          when others then
            Dbms_Output.put_line(p_workspace || ': ' || SQLERRM);
END;
/

它在创建后给我错误。

PL/SQL procedure successfully completed.

WS-38515: ORA-20023: a workspace already exists with the name: 'WS-38515'

如果我单独运行该工作区,那么它可以正常工作。但是当我通过检查可用性检查块时,它不起作用。

execute dbms_wm.CreateWorkspace('WS-38515',isrefreshed=>TRUE);

请帮助任何人。

【问题讨论】:

  • 鉴于您正在硬编码要创建的工作区的名称,我看不到这样一个过程的实用性。现在,如果您将其作为输入参数传递,也许。但即便如此,您多久创建一次新工作空间?编写一个程序的所有这些麻烦,当它归结为它时,发出一个命令。 . . .

标签: sql oracle plsql oracle11g


【解决方案1】:

是否有理由需要动态 SQL、集合和循环来迭代集合?听起来您只想检查该行是否存在,这可以通过简单的count 来完成(您可以通过将其写为where exists 来提高检查效率,但这在这里可能并不重要)

declare
  p_workspace VARCHAR2(100):='WS-38515';
  l_num_workspaces integer;
begin
  select count(*)
    into l_num_workspaces
    from WMSYS.all_workspaces 
   where workspace = p_workspace;

  if( l_num_workspaces = 0 )
  then 
    dbms_wm.CreateWorkspace(p_workspace,isrefreshed=>TRUE);
  end if;
end;

当然,您也可以跳过检查,调用CreateWorkspace,并在异常已经存在时处理它。如果您希望在绝大多数时间创建工作区,那可能会更有效率。

【讨论】:

    【解决方案2】:

    您试图在循环的每次迭代中创建工作区,而不是检查循环中的所有项目,并且只有在所有项目中都没有找到它之后,才创建它。要修复您的代码,它应该是:

    DECLARE
      p_workspace VARCHAR2(100):='WS-38515';
      TYPE t_ws IS TABLE OF VARCHAR2(30);
      v_workspace t_ws;
      p_not_found BOOLEAN := TRUE;
    BEGIN
      SELECT DISTINCT WORKSPACE 
      BULK COLLECT INTO v_workspace;
      FROM WMSYS.all_workspaces 
    
      FOR i IN v_workspace.first..v_workspace.last LOOP
        IF v_workspace(i) <> p_workspace THEN
          p_not_found := FALSE;
          EXIT;
        END IF;
      END LOOP;   
    
      IF p_not_found THEN
         dbms_wm.CreateWorkspace(p_workspace,isrefreshed=>TRUE);
      END IF;
    EXCEPTION
      when others then
        Dbms_Output.put_line(p_workspace || ': ' || SQLERRM);
    END;
    /
    

    但是,您的代码可能只是尝试创建工作区并捕获异常:

    DECLARE
      workspace_exists EXCEPTION;
      PRAGMA EXCEPTION_INIT( workspace_exists, -20023 );
      p_workspace WMSYS.all_workspaces.workspace%TYPE := 'WS-38515';
    BEGIN
      DBMS_WM.CreateWorkspace( p_workspace,isrefreshed=>TRUE);
    EXCEPTION
      WHEN workspace_exists THEN
        DBMS_OUTPUT.PUT_LINE( p_workspace || ': ' || SQLERRM);
    END;
    /
    

    或者,如果DBMS_WM.CreateWorkspace 是一个昂贵的操作,那么:

    DECLARE
      p_workspace WMSYS.all_workspaces.workspace%TYPE := 'WS-38515';
      p_found     WMSYS.all_workspaces.workspace%TYPE;
    BEGIN
      SELECT WORKSPACE
      INTO   p_found;
      FROM   WMSYS.all_workspaces
      WHERE  workspace = p_workspace
      FETCH FIRST ROW ONLY;
    
      DBMS_OUTPUT.PUT_LINE( p_workspace || ': Already Exists' );
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        DBMS_WM.CreateWorkspace( p_workspace,isrefreshed=>TRUE);
    END;
    /
    

    【讨论】:

    • 谢谢,但是之前已经有人回答了.....不过也谢谢你的建议 :-)
    猜你喜欢
    • 1970-01-01
    • 2011-10-29
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    相关资源
    最近更新 更多