【问题标题】:SQL dbms_output.put_line formattingSQL dbms_output.put_line 格式化
【发布时间】:2020-06-06 03:47:59
【问题描述】:

我希望它像您从表(如列)中执行选择查询时一样。我为列名添加了制表符,但在名称和状态之间这样做会抵消一些需求状态,因为名称太长。当 dbms 输出时,它会这样做:

Product Name            Demand Status
------------            -------------
Pro Ski Pole High Demand
Water Bottle High Demand
Intermediate Ski Pole Low Demand
Tire Pump Low Demand
Bicycle Helmet Low Demand
Beginner's Ski Boot Low Demand
Intermediate Ski Boot High Demand
Beginner's Ski Pole Low Demand
Road Bicycle Low Demand
Bicycle Tires Low Demand
Mountain Bicycle Low Demand
Pro Ski Boot Low Demand

代码如下:

declare
STATUS VARCHAR(25);
cursor product_cursor is
SELECT PRODUCT_NAME, COUNT(*) AS DEMAND_STATUS
FROM PRODUCT FULL JOIN ORDER_DETAILS 
ON PRODUCT.PRODUCT_ID = ORDER_DETAILS.PRODUCT_ID
GROUP BY PRODUCT_NAME;
product_row product_cursor%rowtype;
begin
UPDATE PRODUCT
SET PRICE = PRICE - 0
WHERE
    (SELECT COALESCE(MIN(ORDER_ID), 0) 
    FROM ORDER_DETAILS
     WHERE ORDER_DETAILS.PRODUCT_ID = PRODUCT.PRODUCT_ID) =
    (SELECT COALESCE(MAX(ORDER_ID), 0) 
    FROM ORDER_DETAILS
     WHERE ORDER_DETAILS.PRODUCT_ID = PRODUCT.PRODUCT_ID);
dbms_output.put_line('Product Name'||CHR(9)||CHR(9)||CHR(9)||'Demand Status');
dbms_output.put_line('------------'||CHR(9)||CHR(9)||CHR(9)||'-------------');
open product_cursor;
loop
fetch product_cursor into product_row;
exit when product_cursor%notfound;
if PRODUCT_ROW.DEMAND_STATUS < 2 THEN
STATUS := 'Low Demand';
else
STATUS := 'High Demand';
end if;
dbms_output.put_line(PRODUCT_ROW.PRODUCT_NAME||' '||STATUS);
end loop;
close product_cursor;
end;

【问题讨论】:

  • 你打算在一天结束时使用 dbms_output 做什么?
  • 可能更容易只有一个 sp 并返回一个 sqlplus/sqldev 可以打印的 refcursor
  • 您希望在输出中看到什么?你能在实际输出下面放一个期望输出的例子吗?
  • 只是一个旁注。即使您得到正确的字符定位(根据@Alex 的建议),除非您还确保 Dbms_Output 的目标始终使用等宽字体,否则垂直对齐列的努力注定会失败。

标签: sql oracle plsql oracle-sqldeveloper dbms-output


【解决方案1】:

你可能最好不使用标签,而是这样做:

dbms_output.put_line(rpad('Product Name', 51)||'Demand Status');
dbms_output.put_line(rpad('------------', 51)||'-------------');
...
dbms_output.put_line(rpad(PRODUCT_ROW.PRODUCT_NAME, 51)||STATUS);

其中 51 代表您实际期望的最大产品名称,我任意猜测为 50,加上一个作为差距。

如果您希望产品名称列完全下划线,您可以这样做:

dbms_output.put_line(rpad('Product Name', 51)||'Demand Status');
dbms_output.put_line(rpad('-', 50, '-')||' '||'-------------');
...
dbms_output.put_line(rpad(PRODUCT_ROW.PRODUCT_NAME, 51)||STATUS);

dbms_output 用于除调试以外的任何事情都会让您在以后感到头疼,因此最好将product_cursor 返回给客户端并让它显示出来;类似的东西(假设 SQL*Plus 或类似的):

var rc refcursor

declare
product_row product_cursor%rowtype;
begin
UPDATE PRODUCT
SET PRICE = PRICE - 0
WHERE
    (SELECT COALESCE(MIN(ORDER_ID), 0) 
    FROM ORDER_DETAILS
     WHERE ORDER_DETAILS.PRODUCT_ID = PRODUCT.PRODUCT_ID) =
    (SELECT COALESCE(MAX(ORDER_ID), 0) 
    FROM ORDER_DETAILS
     WHERE ORDER_DETAILS.PRODUCT_ID = PRODUCT.PRODUCT_ID);

  open :rc for (
    SELECT PRODUCT_NAME,
      CASE WHEN COUNT(*) < 2 THEN 'Low Demand' ELSE 'High Demand' END AS STATUS
    FROM PRODUCT FULL JOIN ORDER_DETAILS 
    ON PRODUCT.PRODUCT_ID = ORDER_DETAILS.PRODUCT_ID
    GROUP BY PRODUCT_NAME;
end;
/

print rc

不过,您在这里使用 PL/SQL 的原因并不明显;您可以只使用两条 SQL 语句:

UPDATE PRODUCT
SET PRICE = PRICE - 0
WHERE
    (SELECT COALESCE(MIN(ORDER_ID), 0) 
    FROM ORDER_DETAILS
     WHERE ORDER_DETAILS.PRODUCT_ID = PRODUCT.PRODUCT_ID) =
    (SELECT COALESCE(MAX(ORDER_ID), 0) 
    FROM ORDER_DETAILS
     WHERE ORDER_DETAILS.PRODUCT_ID = PRODUCT.PRODUCT_ID);

SELECT PRODUCT_NAME,
  CASE WHEN COUNT(*) < 2 THEN 'Low Demand' ELSE 'High Demand' END AS STATUS
FROM PRODUCT FULL JOIN ORDER_DETAILS 
ON PRODUCT.PRODUCT_ID = ORDER_DETAILS.PRODUCT_ID
GROUP BY PRODUCT_NAME;

【讨论】:

    猜你喜欢
    • 2011-08-25
    • 2015-03-26
    • 1970-01-01
    • 2019-11-18
    • 2021-11-26
    • 2013-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多