Как я могу распечатать результаты процедуры SQL? - PullRequest
0 голосов
/ 06 ноября 2019

Я пишу процедуру подсчета строк в каждой таблице в моей базе данных. Пока это выглядит так:

create or replace procedure count_database_rows()
dynamic result sets 1
P1: begin atomic
DECLARE stmt CHAR(40);--
  FOR v1 AS
      c1 CURSOR FOR
   SELECT TABLE_SCHEMA, TABLE_NAME FROM sysibm.tables
    DO
       SET stmt = 'SELECT COUNT(*) FROM '||TABLE_SCHEMA||'.'||TABLE_NAME;--
       PREPARE s FROM stmt;--
       EXECUTE s;--
  END FOR;--
end P1
~

однако, когда я запускаю его:

db2 -ntd~ -f script.sql > dump.csv

все, что я получаю, это:

DB20000I  The SQL command completed successfully.

как можноВместо этого я печатаю все результаты?

Ответы [ 2 ]

3 голосов
/ 06 ноября 2019

Просто для демонстрации. Я предполагаю, что это какое-то образовательное задание, и это Db2 для LUW.

Для не-DPF Db2 только для систем LUW

--#SET TERMINATOR @
CREATE OR REPLACE FUNCTION COUNT_DATABASE_ROWS()
RETURNS TABLE (P_TABSCHEMA VARCHAR(128), P_TABNAME VARCHAR(128), P_ROWS BIGINT)
BEGIN
  DECLARE L_STMT VARCHAR(256);
  DECLARE L_ROWS BIGINT;

  FOR V1 AS 
    SELECT TABSCHEMA, TABNAME 
    FROM SYSCAT.TABLES 
    WHERE TYPE IN ('T', 'S')
    FETCH FIRST 10 ROWS ONLY
  DO
    SET L_STMT = 'SET ? = (SELECT COUNT(*) FROM "'||V1.TABSCHEMA||'"."'||V1.TABNAME||'")';
    PREPARE S FROM L_STMT;
    EXECUTE S INTO L_ROWS;
    PIPE(V1.TABSCHEMA, V1.TABNAME, L_ROWS);
  END FOR;
  RETURN;
END@

SELECT * FROM TABLE(COUNT_DATABASE_ROWS())@

Для любого Db2 для систем LUW

Немного сложно для систем DPF, но выполнимо. Мы должны обернуть код, который не разрешен в операторе inlined compound, в хранимую процедуру.

--#SET TERMINATOR @
CREATE OR REPLACE PROCEDURE COUNT_DATABASE_ROWS_DPF(OUT P_DOC XML)
READS SQL DATA
BEGIN 
  DECLARE L_STMT VARCHAR(256);
  DECLARE L_ROWS BIGINT;
  DECLARE L_NODE XML;

  SET P_DOC = XMLELEMENT(NAME "DOC");

  FOR V1 AS 
    SELECT TABSCHEMA, TABNAME 
    FROM SYSCAT.TABLES 
    WHERE TYPE IN ('T', 'S')
    FETCH FIRST 10 ROWS ONLY
  DO
    SET L_STMT = 'SET ? = (SELECT COUNT(*) FROM "'||V1.TABSCHEMA||'"."'||V1.TABNAME||'")';
    PREPARE S FROM L_STMT;
    EXECUTE S INTO L_ROWS;
    SET L_NODE = XMLELEMENT
    (
      NAME "NODE"
    , XMLELEMENT(NAME "TABSCHEMA", V1.TABSCHEMA)
    , XMLELEMENT(NAME "TABNAME", V1.TABNAME)
    , XMLELEMENT(NAME "ROWS", L_ROWS)
    );
    SET P_DOC = XMLQUERY
    (
      'transform copy $mydoc := $doc modify do insert $node as last into $mydoc return $mydoc'
      passing P_DOC as "doc", L_NODE as "node"
    );
  END FOR;
END@

CREATE OR REPLACE FUNCTION COUNT_DATABASE_ROWS_DPF()
RETURNS TABLE (P_TABSCHEMA VARCHAR(128), P_TABNAME VARCHAR(128), P_ROWS BIGINT)
BEGIN ATOMIC
  DECLARE L_DOC XML;

  CALL COUNT_DATABASE_ROWS_DPF(L_DOC);
  RETURN
  SELECT *
  FROM XMLTABLE ('$D/NODE' PASSING L_DOC AS "D" COLUMNS 
    TYPESCHEMA VARCHAR(128) PATH 'TABSCHEMA'
  , TABNAME    VARCHAR(128) PATH 'TABNAME'
  , LENGTH     BIGINT       PATH 'ROWS'
  );
END@

-- Usage. Either CALL or SELECT:
CALL COUNT_DATABASE_ROWS_DPF(?)@
SELECT * FROM TABLE(COUNT_DATABASE_ROWS_DPF())@
2 голосов
/ 06 ноября 2019

Если ваш Db2-сервер работает в Linux / Unix / Windows, вы можете использовать функцию DBMS_OUT.PUT_LINE для отправки диагностического вывода из подпрограмм SQL на консоль. Идея состоит в том, что в вашей подпрограмме вы присваиваете переменной некоторый текст (например, имя таблицы и ее количество), а затем вызываете DBMS_OUTPUT.PUT_LINE (...), чтобы этот текст появлялся на консоли. Недостаток этого подхода заключается в том, что выходные данные появятся только после завершения процедуры. Это часто не то, что вам нужно, иногда вы хотите видеть количество строк по мере их появления, поэтому вместо этого рассмотрите альтернативные подходы, как показано ниже.

Чтобы увидеть вывод DBMS_OUTPUT.PUT_LINE с Db2 CLP (илиdb2cmd.exe) сначала нужно использовать set serveroutput on перед вызовом процедуры.

Но для таких простых вещей, как эта, хранимая процедура может быть неподходящей, потому что вы можете использовать CLP для выполнения работы в два этапапосле подключения к базе данных. Это часто более удобно для сценариев. Идея состоит в том, что вы создаете файл для генерации запросов, который при запуске с CLP создает второй файл, и вы выполняете второй файл для получения желаемых результатов.

Пример

Создатьфайл gen_counts.sql, содержащий запрос, который генерирует реальные запросы, например, gen_counts.sql, может содержать

select 'select count(*) from '||rtrim(tabschema)||'.'||rtrim(tabname)||' with ur;' from syscat.tables;

Затем вы можете выполнить следующие действия:

db2 connect to $database
db2 -txf gen_counts.sql > count_queries.sql
db2 -tvf count_queries.sql > count_results.txt

Обратите внимание, что выходной файл (в данном случае count_results.txt) доступен для чтения через другой сеанс оболочки, пока скрипт продолжает работать. При необходимости вы также можете направить вывод в параллельные задания.

Однако опытные администраторы баз данных могут избежать подсчета строк во всех таблицах таким способом и вместо этого могут предпочесть убедиться, что runstats всегда обновлены длявсех таблиц и принимают последние оценки количества строк, которые отображаются в SYSCAT.TABLES.CARD после завершения выполнения runstats. Если статистика актуальна, счет КАРТЫ часто достаточно хорош для многих целей. Если требуются точные значения, они часто действительны только для определенной временной отметки, если база данных активна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...