Oracle PL/SQL - 如何转义冒号 (:),被误解为绑定变量
我有一个小的 PL/SQL 脚本,用于尝试在两个 Oracle 数据库实例之间复制数据。
我使用(经过清理的)调用 SQL 脚本:
sqlplus username/[email protected]:1434/SERVICENAME @copyTables.sql source_username source_password source_connstring destination_username destination_password destination_connstring
copyTables.sql 脚本:
SET SERVEROUTPUT ON;
DECLARE
source_username VARCHAR2(20) := &1
source_password VARCHAR2(20) := &2
source_connstring VARCHAR2(2) := &3
destination_username VARCHAR2(20) := &4
destination_password VARCHAR2(20) := &5
destination_connstring VARCHAR(20) := &6
CURSOR user_table_cur IS
SELECT table_name
FROM user_tables
ORDER BY table_name DESC;
BEGIN
FOR user_table IN user_table_cur LOOP
dbms_output.put_line(source_username);
dbms_output.put_line(user_table.table_name);
COPY FROM {source_username}/{source_password}@{source_connstring} TO {destination_username}/{destination_password}@{destination_connstring} APPEND user_table.table_name user_table.table_name USING SELECT* FROM user_table.table_name;
END LOOP;
END;
唯一的问题是,当我运行此脚本时,它似乎误解了连接字符串中的冒号 (:) 与绑定变量有关的内容:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
old 2: source_username VARCHAR2(20) := &1
new 2: source_username VARCHAR2(20) := SANITISED
old 3: source_password VARCHAR2(20) := &2
new 3: source_password VARCHAR2(20) := SANITISED
old 4: source_connstring VARCHAR2(2) := &3
new 4: source_connstring VARCHAR2(2) := server.com:3630/SANITISED
old 5: destination_username VARCHAR2(20) := &4
new 5: destination_username VARCHAR2(20) := SANITISED
old 6: destination_password VARCHAR2(20) := &5
new 6: destination_password VARCHAR2(20) := SANITISED
old 7: destination_connstring VARCHAR(20) := &6
new 7: destination_connstring VARCHAR(20) := server.com:3630/SANITISED
SP2-0552: Bind variable "3630" not declared.
SQL> Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
I已经用大括号 ({}) 转义了上面的内容,但它似乎仍然抱怨绑定变量。
另外 - 作为附录 - 我上面所做的方式,这是将命令行参数传递给 PL/SQL 脚本的最佳实践吗?我愿意接受有关更好方法的建议。
干杯, 胜利者
I have a small PL/SQL script that I'm using to try and copy data between two Oracle database instances.
I'm calling the SQL script with (sanitised):
sqlplus username/[email protected]:1434/SERVICENAME @copyTables.sql source_username source_password source_connstring destination_username destination_password destination_connstring
The copyTables.sql script:
SET SERVEROUTPUT ON;
DECLARE
source_username VARCHAR2(20) := &1
source_password VARCHAR2(20) := &2
source_connstring VARCHAR2(2) := &3
destination_username VARCHAR2(20) := &4
destination_password VARCHAR2(20) := &5
destination_connstring VARCHAR(20) := &6
CURSOR user_table_cur IS
SELECT table_name
FROM user_tables
ORDER BY table_name DESC;
BEGIN
FOR user_table IN user_table_cur LOOP
dbms_output.put_line(source_username);
dbms_output.put_line(user_table.table_name);
COPY FROM {source_username}/{source_password}@{source_connstring} TO {destination_username}/{destination_password}@{destination_connstring} APPEND user_table.table_name user_table.table_name USING SELECT* FROM user_table.table_name;
END LOOP;
END;
The only issue is that when I run this, it seems to misinterpret a colon (:) in the connection string for something to do with bind variables:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
old 2: source_username VARCHAR2(20) := &1
new 2: source_username VARCHAR2(20) := SANITISED
old 3: source_password VARCHAR2(20) := &2
new 3: source_password VARCHAR2(20) := SANITISED
old 4: source_connstring VARCHAR2(2) := &3
new 4: source_connstring VARCHAR2(2) := server.com:3630/SANITISED
old 5: destination_username VARCHAR2(20) := &4
new 5: destination_username VARCHAR2(20) := SANITISED
old 6: destination_password VARCHAR2(20) := &5
new 6: destination_password VARCHAR2(20) := SANITISED
old 7: destination_connstring VARCHAR(20) := &6
new 7: destination_connstring VARCHAR(20) := server.com:3630/SANITISED
SP2-0552: Bind variable "3630" not declared.
SQL> Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
I've already escape the above with braces ({}), but it still seems to complain about bind variables.
Also - as a addendum - the way I'm doing above, is this the best practice in passing command-line arguments through to a PL/SQL script? I'm open to suggestions on better methods of doing this.
Cheers,
Victor
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
分配位置变量时,您需要在位置变量周围加上引号,因此整个值在此时被解释为字符串:
我不认为 PL/SQL 变量分配支持转义,就像
LIKE
确实如此,如果确实如此,您必须在调用脚本之前修改您的输入,这将是不理想的。Moving away from your original question a bit...
您还需要使用某种形式的动态 SQL 根据传递的参数和游标值采取操作;
COPY
是一个 SQL*Plus 命令,因此无论如何您都无法从 PL/SQL 调用它。我建议您使用 PL/SQL 块通过 spool 和 dbms_output 生成一个包含所有命令的单独 SQL 脚本,然后在该块完成后执行该脚本。类似于:远离你原来的问题...
你甚至不需要为此使用 PL/SQL,除非你想使用动态 SQL 和 EXECUTE IMMEDIATE。这将与前面的示例执行相同的操作:
You need to put quotes around the positional variable when you assign it, so the whole value is interpreted as a string at that point:
I don't believe PL/SQL variable assignment supports escaping in the sense that
LIKE
does, and if it did you'd have to modify your inputs before you called the script which wouldn't be ideal.Moving away from your original question a bit...
You'll also need to use some form of dynamic SQL to take action based on the passed parameters and cursor values; and
COPY
is an SQL*Plus command so you can't call it from PL/SQL anyway. I'd suggest you use the PL/SQL block to generate a separate SQL script containing all the commands, viaspool
anddbms_output
, which you then execute after the block completes. Something like:Moving even further away from your original question...
You don't even need to use PL/SQL for this, unless you want to use dynamic SQL and
EXECUTE IMMEDIATE
. This will do the same as the earlier example:尝试在两个 Oracle 数据库实例之间复制数据。
您将 SQL*Plus 命令与 PL/SQL 混合在一起。但是,无需为此自行编写代码。您可以使用Oracle Data Pump 导出和导入。将其与 CONTENT=DATA_ONLY 选项一起使用来模拟 SQL*Plus 的 COPY 命令。
问候,
抢。
to try and copy data between two Oracle database instances.
You're mixing up SQL*Plus commands with PL/SQL. But, there is no need to write code yourself for that. You can use Oracle Data Pump Export and Import. Use it with the CONTENT=DATA_ONLY option to mimic SQL*Plus' COPY command.
Regards,
Rob.