เรียกใช้งานสคริปต์ด้วย SQLPlus ที่มีช่องว่างเซมิโคลอนและเครื่องหมายสแลช


15

ในบางครั้งฉันจะได้รับสคริปต์ที่จะทำงานได้ดีใน SQL Developer หรือ Toad แต่ต้องการการปรับเปลี่ยนเพื่อให้สามารถเรียกใช้จาก SQL * Plus ได้สำเร็จ นี่เป็นตัวอย่างกรณีที่เลวร้ายที่สุดที่มีหลายประโยคคำสั่งที่มีบรรทัดว่างเซมิโคลอนและเครื่องหมายสแลช:

INSERT INTO t1 VALUES ('a

;
/
');

INSERT INTO t1 VALUES ('b

;
/
');

DELETE FROM t1 WHERE c1 = 'c

;
/
';

ด้วยเหตุผลต่างๆคำสั่งเหล่านี้จำเป็นต้องเรียกใช้จาก SQL * Plus บรรทัดว่างจะแก้ไขได้ง่ายด้วย ...

set sqlblanklines on

ฉันทราบว่าsqlterminatorสามารถเปลี่ยนแปลงและ / หรือปิดการใช้งาน แต่ทั้งคู่จะต้องมีการปรับเปลี่ยนรหัสก่อนหน้านี้จะย้ายปัญหาโดยไม่ต้องแก้ไขและไม่สามารถแก้ไขปัญหาที่ฝังอยู่ในสแลชได้

คำตอบที่ดีที่สุดคือวิธีที่จะอนุญาตให้ข้อความเหล่านี้ทำงานโดยไม่มีการแก้ไขโดยการเปลี่ยนแปลงสภาพแวดล้อมในบางวิธี (เช่นเดียวกับ sqlblanklines) หากไม่สามารถทำได้อาจมีวิธีแก้ไขสคริปต์โดยทางโปรแกรม ฉันพยายามหลีกเลี่ยงการเปลี่ยนแปลงด้วยตนเอง


ปัญหานี้สามารถเกิดขึ้นได้อย่างง่ายดายเมื่อใช้การดำเนินการบรรทัดคำสั่งของ SQLPLUS ขณะที่คุณอยู่ในโปรแกรม SQLPLUS ตัวแก้ไขบรรทัดคำสั่งยังคงทำงานอยู่ ดังนั้นไอเท็มที่เกี่ยวข้องกับตัวแก้ไขบรรทัดคำสั่ง (พื้นที่ว่างถูกตีความว่าเป็นคำสั่ง / ตัวแปรเซมิโคลอนจะถูกมองว่าเป็นจุดสิ้นสุดของคำสั่ง) นั่นคือสาเหตุที่การใช้ '@' ในรหัสผ่านทำให้ไม่มีอะไรนอกจากความเสียใจเมื่อคุณพยายามลงชื่อเข้าใช้ (ทุกสิ่งที่อยู่ทางด้านขวาของ @ ถูกมองว่าเป็นชื่อของ DB) ในระหว่างการปรับใช้ที่สำคัญเราพบปัญหาเกี่ยวกับช่องว่างที่บังคับให้เราปรับใช้สิ่งต่าง ๆ ผ่านทางคางคก SQLPLUS ไม่มีประโยชน์กับ
TomV

ขอบคุณสำหรับความคิดของคุณ ดังนั้นเพื่อชี้แจงให้ชัดเจนคือคำตอบของคุณว่าสิ่งที่ฉันขอเป็นไปไม่ได้?
Leigh Riffel

คุณสามารถแปลงค่า carriage return ภายในสตริงเป็น chr (10) s insert ถูกแสดงไว้ในหนึ่งบรรทัดได้หรือไม่?
Chris Saxon

@ChrisSaxon ฉันทำได้ แต่ปัญหานี้เป็นวิธีแยกแยะผลตอบแทนที่ควรเข้ารหัสและส่งคืนที่ต้องอยู่คนเดียวโดยเป็นส่วนหนึ่งของไวยากรณ์ หากคุณมีวิธีการทำเช่นนี้โปรดโพสต์สิ่งนี้เป็นคำตอบ
Leigh Riffel

คำตอบ:


8

คุณสามารถทำสิ่งนี้ได้โดยใช้ login.sql login.sql ดำเนินการระหว่าง - น่าแปลกใจ - เข้าสู่ระบบและโหลดจาก SQLPATH หรือไดเรกทอรีปัจจุบันของคุณ สำหรับตัวอย่างที่คุณให้คุณเลือกกรณีที่แย่ที่สุด

ปัญหาคือ sqlterminator สิ่งที่คุณใส่เข้าไปที่นั่นเครื่องหมายทับหน้าจะถูกรักษาไว้เป็น sqlterminator ฟรี ถัดจากนั้น sqlplus จะสแกนหา sqlterminator ก่อนและทำสิ่งนี้ก่อนที่จะสแกนไปยังตัวสิ้นสุดของสตริง ข้อบกพร่องถ้าคุณถามฉัน สแลชไปข้างหน้าสามารถใช้ในสตริงตราบใดที่มันไม่ได้อยู่คนเดียวในบรรทัดแยก ทันทีที่ sqlplus ค้นหาอักขระที่ระบุเป็น sqlterminator มันจะไม่สนใจทุกสิ่งและหยุดอ่าน

สแลชไปข้างหน้าสามารถจัดการได้ตราบใดที่มันไม่ได้อยู่คนเดียวในบรรทัด

login.sql ประกอบด้วย:

prompt run login.sql
show sqlterminator
show sqlblanklines
set sqlblanklines on
set sqlterminator ';'
show sqlterminator
show sqlblanklines
prompt ready login.sql
set echo on

leigh.sql ประกอบด้วย:

INSERT INTO t1 VALUES ('fail bc semicolon
a;a
/
'); 

INSERT INTO t1 VALUES ('fail bc solo /


aa
/
');

INSERT INTO t1 VALUES ('ok / not solo


aa
/a
');

DELETE FROM t1 WHERE a = 'c


a/
';

เรียกใช้สคริปต์:

sqlplus leigh/leigh@orcl @leigh
SQL*Plus: Release 10.2.0.4.0 - Production on Thu Aug 9 22:36:20 2012

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options

run login.sql
sqlterminator ";" (hex 3b)
sqlblanklines OFF
sqlterminator ";" (hex 3b)
sqlblanklines ON
ready login.sql
SQL> INSERT INTO t1 VALUES ('fail bc semicolon
  2  a;a
  3  /
ERROR:
ORA-01756: quoted string not properly terminated


SQL> ');
SP2-0042: unknown command "')" - rest of line ignored.
SQL> 
SQL> INSERT INTO t1 VALUES ('fail bc solo /
  2  
  3  
  4  aa
  5  /
ERROR:
ORA-01756: quoted string not properly terminated


SQL> ');
SP2-0042: unknown command "')" - rest of line ignored.
SQL> 
SQL> INSERT INTO t1 VALUES ('ok / not solo
  2  
  3  
  4  aa
  5  /a
  6  ');

1 row created.

SQL> 
SQL> DELETE FROM t1 WHERE a = 'c
  2  
  3  
  4  a/
  5  ';

0 rows deleted.

ไม่จำเป็นต้องเล่นซอกับบล็อกเริ่มต้น / สิ้นสุด ไม่สามารถจัดการ sqlterminator ภายในคำสั่งไม่ว่ามันจะอยู่ที่ไหนในสตริงหรือไม่ไม่สามารถจัดการกับเส้นด้วยสแลชไปข้างหน้าคนเดียวในบรรทัดในสตริง


1
ขอบคุณสำหรับการพิสูจน์ ฉันใช้การตั้งค่าไฟล์ login.sql ในทำนองเดียวกัน โดยพื้นฐานแล้วสิ่งนี้ยืนยันว่าทำไมฉันถึงทำไม่ได้
Leigh Riffel

1
ความแตกต่างเล็กน้อยคือการใช้สคริปต์นักวิ่งที่ทำการตั้งค่าและเรียกสคริปต์จริง จะกลายเป็น sqlplus leigh / leigh @ orcl @runner leigh นั่นเป็นความยืดหยุ่นมากกว่า login.sql
ik_zelf

1

แทรกคำสั่งที่มีบรรทัดว่างและเซมิโคลอนจะสำเร็จถ้าวางไว้ในบล็อก BEGIN ... END การเปลี่ยนแปลงนี้สามารถทำได้โดยใช้สคริปต์ แต่สคริปต์จะล้มเหลวหากมีคำสั่ง DDL ที่ไม่สามารถเรียกใช้ภายในบล็อกโดยไม่ต้องดำเนินการทันที

การแก้ปัญหานี้ยังไม่สามารถแก้ไขปัญหา / ฝังตัว


ในอดีตที่ผ่านมาฉันใช้สคริปต์ Perl / DBD เพื่อทำเช่นนี้เพื่อหลีกเลี่ยง sqlplus มีความสุขที่จะแบ่งปัน ...
Philᵀᴹ

@Phil ขอบคุณ แต่ SQLPlus ทำงานได้ดีใน 99.9% ของสถานการณ์ดังนั้นฉันไม่ควรเพิ่มเครื่องมืออื่นลงในการผสม
Leigh Riffel

1

วิธีแก้ปัญหาของฉัน:

         begin
             INSERT INTO t1 VALUES ('a

             ;
             ');
         end;
         /

ดูเหมือนว่าคำสั่งยกเลิกจะถูกละเว้นภายในงบร่างกาย


ดูคำตอบของฉันเพราะเหตุใดจึงไม่ใช่วิธีแก้ปัญหาที่ดีสำหรับคำสั่ง DDL หรือเครื่องหมายทับที่ฝัง
Leigh Riffel

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.