oracle PLSQL在数据库中搜索值

gwo2fgha  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(132)

我最近从非常了解MSSQL转向使用PLSQL。我在MSSQL中拥有的一组非常有用的脚本是用于理解没有文档或建议可用的数据库的结构(遗憾的是,这种情况太常见了)。这些工具之一是一个脚本,用于在数据库中搜索特定的值(例如,我正在尝试为PLSQL复制该脚本。我在这里尝试开发的脚本是搜索一个整数值。
我所采用的方法是创建一个临时表的模式/表/列的数值列,然后创建动态SQL来计算有多少行在每个示例中包含我正在搜索的值。最后,我选择匹配数大于零的行。我在脚本中声明临时表时遇到了困难。我使用SQL Developer。我的剧本就在下面。

DECLARE cSQL VARCHAR2(1000);
        iSearchValue INT;

CREATE PRIVATE TEMPORARY TABLE ORA$PTT_COL_MATCHES
(
    SCHEMA_NAME VARCHAR2(100),
    TABLE_NAME VARCHAR2(100),
    COLUMN_NAME VARCHAR2(100),
    DATA_TYPE VARCHAR2(100),
    MATCH_COUNT INT
)
ON COMMIT PRESERVE DEFINITION;

BEGIN
    iSearchValue := 237001;
    
    
    INSERT INTO ORA$PTT_COL_MATCHES
            (SCHEMA_NAME,
            TABLE_NAME,
            COLUMN_NAME,
            DATA_TYPE,
            MATCH_COUNT)
    SELECT  col.owner as schema_name,
            col.table_name, 
            col.column_name,
            col.data_type,
            0
    FROM    sys.all_tab_columns col
            INNER JOIN sys.all_tables t     ON      col.owner = t.owner 
                                            AND     col.table_name = t.table_name
    WHERE   col.owner NOT IN ('SYS', 'SYSTEM');
    --AND     col.DATA_TYPE IN ('INT', 'NUMBER', 'FLOAT', 'LONG')
            
            
    FOR rec IN
        (SELECT  *
        FROM    ORA$PTT_COL_MATCHES)
    LOOP
        cSQL = 'UPDATE  ' || ORA$PTT_COL_MATCHES || '
                SET     MATCH_COUNT = (SELECT COUNT(*) FROM ' || rec.SCHEMA_NAME || '.' || rec.TABLE_NAME || ' WHERE ' || rec.COLUMN_NAME || ' = ' || TO_CHAR(iSearchValue) || ')
                WHERE   SCHEMA_NAME = ''' || rec.SCHEMA_NAME || '''
                AND     TABLE_NAME = ''' || rec.TABLE_NAME || '''';
        EXECUTE IMMEDIATE cSQL;
    END LOOP;
    
    
    SELECT  *
    FROM    ORA$PTT_COL_MATCHES
    WHERE   MATCH_COUNT > 0;
    
    
END;

我收到的错误是:

Error report -
ORA-06550: line 4, column 1:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:

   begin function pragma procedure subtype type <an identifier>
   <a double-quoted delimited-identifier> current cursor delete
   exists prior
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:

在SQL Developer中,我手动选择要执行的整个脚本。我明白上面的错误表明我不能在脚本中的那个点使用CREATE。我的问题是:
1.为什么我不能在那里创建一个临时表,
1.我在哪里可以创建它,因为BEGIN-END块内部也不起作用?
1.奖励问题:在PLSQL中有更好的方法吗?

56lgkhnf

56lgkhnf1#

CREATE TABLE是一个SQL语句,你不能在PL/SQL中使用SQL语句。您需要在PL/SQL块之前执行此操作,或者使用EXECUTE IMMEDIATE(这将在PL/SQL块中创建一个SQL范围)。类似地,您不能在PL/SQL块中单独使用SELECT语句;你要么想要SELECT ... [BULK COLLECT] INTO ...,要么使用SELECT的光标。
你也可以(也应该)在动态SQL语句中尽可能地使用绑定变量,以最大限度地降低SQL注入攻击的风险。

CREATE PRIVATE TEMPORARY TABLE ORA$PTT_COL_MATCHES
(
    SCHEMA_NAME VARCHAR2(100),
    TABLE_NAME VARCHAR2(100),
    COLUMN_NAME VARCHAR2(100),
    DATA_TYPE VARCHAR2(100),
    MATCH_COUNT INT
)
ON COMMIT PRESERVE DEFINITION;

DECLARE
  cSQL         VARCHAR2(1000);
  iSearchValue INT;
BEGIN
  iSearchValue := 237001;

  INSERT INTO ORA$PTT_COL_MATCHES(
    SCHEMA_NAME,
    TABLE_NAME,
    COLUMN_NAME,
    DATA_TYPE,
    MATCH_COUNT
  )
  SELECT  col.owner as schema_name,
          col.table_name, 
          col.column_name,
          col.data_type,
          0
  FROM    all_tab_columns col
  WHERE   col.owner IN (USER) -- NOT IN ('SYS', 'SYSTEM')
  AND     col.DATA_TYPE IN ('INT', 'NUMBER', 'FLOAT');

  FOR rec IN (
    SELECT  *
    FROM    ORA$PTT_COL_MATCHES
  )
  LOOP
      cSQL := 'UPDATE ORA$PTT_COL_MATCHES
               SET    MATCH_COUNT = (SELECT COUNT(*)
                                     FROM   "' || rec.SCHEMA_NAME || '"."' || rec.TABLE_NAME || '"
                                     WHERE  "' || rec.COLUMN_NAME || '" = :search_value
                                    )
               WHERE  SCHEMA_NAME = :schema_name
               AND    TABLE_NAME  = :table_name
               AND    COLUMN_NAME = :column_name';
      EXECUTE IMMEDIATE cSQL
        USING TO_CHAR(iSearchValue), rec.SCHEMA_NAME, rec.TABLE_NAME, rec.COLUMN_NAME;
  END LOOP;
END;
/

SELECT  *
FROM    ORA$PTT_COL_MATCHES
WHERE   MATCH_COUNT > 0;

fiddle

相关问题