我最近从非常了解 MSSQL 转向使用 PLSQL。我在 MSSQL 中拥有的一组真正有用的脚本是用于理解没有可用文档或建议的数据库结构(遗憾的是,这种情况经常出现)。这些工具之一是用于在数据库中搜索特定值(例如 ID)的脚本。我正在尝试为 PLSQL 复制该脚本。我在这里尝试开发的脚本是搜索整数值。
我采用的方法是创建一个由架构/表/数字列组成的临时表,然后创建动态 SQL 来计算每个实例中有多少行包含我正在搜索的值。最后,我选择匹配数大于零的行。我在脚本中声明临时表时遇到困难。我正在使用 SQL 开发人员。到目前为止我的脚本如下。
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。我的问题是:
CREATE TABLE
是DDL语句,不能在PL/SQL中使用DDL语句。您需要在 PL/SQL 块之前执行此操作或使用 EXECUTE IMMEDIATE
。同样,您不能在 PL/SQL 块中单独使用 SELECT
语句;您需要 SELECT ... [BULK COLLECT] INTO ...
或使用带有 SELECT
的光标:
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 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;
END;
/
SELECT *
FROM ORA$PTT_COL_MATCHES
WHERE MATCH_COUNT > 0;