我最近从非常了解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中有更好的方法吗?
1条答案
按热度按时间56lgkhnf1#
CREATE TABLE
是一个SQL语句,你不能在PL/SQL中使用SQL语句。您需要在PL/SQL块之前执行此操作,或者使用EXECUTE IMMEDIATE
(这将在PL/SQL块中创建一个SQL范围)。类似地,您不能在PL/SQL块中单独使用SELECT
语句;你要么想要SELECT ... [BULK COLLECT] INTO ...
,要么使用SELECT
的光标。你也可以(也应该)在动态SQL语句中尽可能地使用绑定变量,以最大限度地降低SQL注入攻击的风险。
fiddle