sql >> データベース >  >> RDS >> Mysql

すべてのテーブルを表示します。説明のような機能

    これは、ここ で与えられた回答を拡張したものです。 。文字セット列と照合列を追加し、データベースレベルとテーブルレベルでも同じです。 こちら と同様に計算されたアルファベット順とテーブルサイズによる2つの選択肢で並べ替える必要条件が含まれています 。コンセプトにはまだピアレビューが必要だと思います。 DBAのRolandoこちら 方法を示していた、そしてリック・ジェームスはコメントした。これは単純な計算ではなく、TEXTなどの非静的データを組み込むことはありません。 およびBLOB s。したがって、その計算を自由に改善して共有してください。とにかく、テーブルは通常、「サイズ」の場合、目的のソート順で返されます。 InnoDBファイルサイズに関連するため、その正確性については一切保証しません。

    それはあなたがソート機能を改善するためのスタブを可能にします。たとえば、メインテーブルとサポートテーブルおよびコードテーブルに基づいて、並べ替え順序の結合用に別のテーブルを作成します。

    セッション: これは、ルーチンを呼び出す単なるインスタンスであるセッションの概念に依存しています。それらをスナップショットと考えてください 後でアクセスできます。その時点のデータは、セッションスナップショットに含まれています。テーブルを変更するときに役立つ場合があります。特に、照合。ああ、そして照合については、開発者がインターネットからコードを切り取って貼り付けるときに、正しくない照合設定が原因で外部キー制約が失敗することがよくあります(テーブルレベルと列レベルの文字セットと照合の不一致)。それが私がこのバージョンにそれを投げ込んだ理由です。

    ルーチンはデータベースに存在しますReporting101a これには、2つのストアドプロシージャといくつかのサポートテーブル(ほとんどすべてのセッションベース)が含まれています。約5つのテーブル。

    呼び出し例:

    1. call Reporting101a.describeTables_v3('myDb',@theOutVar,false,true,'size')
    2. call Reporting101a.describeTables_v3('myDb',@theOutVar,false,true,'alpha')
    3. call Reporting101a.Print_Tables_Like_Describe(4,'size')

    NoteAを参照してください

    パラメータ(最初のストアドプロシージャ):

    1. すべてのテーブルを説明するデータベース名。
    2. INT OUT セッションを保持するパラメータ#
    3. ブール値:最後にレポートテーブルからデータを削除しますか
    4. boolean:describeを生成するPrettyPrintingストアドプロシージャを自動呼び出す必要があります -出力のように。
    5. 並べ替え順序:「サイズ」または「アルファ」。実際、「サイズ」以外は「アルファ」になります。

    パラメータ(Pretty Printing Stored Proc):

    1. 以前に保存されたスナップショットのセッション番号。
    2. 上記のように順序を並べ替えます。

    コードはかなりよく文書化されていますが、400行に対して600行のコードに変換することはできません。

    ルーチンは、Reporting101aで自己完結型であり、自己参照型です。 データベース。したがって、どこからでも明示的に呼び出します。

    注A: 上記の例について:例。 1と2 同様に、ソート順が異なります。これらは、1つで使用する通常の方法です。 電話。テーブルサイズは常にテーブル名の横に表示されます。 'size'でのみ、降順で並べ替えられます その上に。 4番目のパラメータをTrueとして使用 、最後にPretty PrintingStoredProcを自動呼び出しします。それ以外の場合は、プレーンジェーンの結果セットがレンダリングされます。 @theOutVar 作成されたセッション番号を表すために書き込まれます。これは、その後すぐにPretty Printingストアドプロシージャを手動で呼び出したり、ルーチンの1つをウェッジしてデータを使用したり、数か月後に(フリーズしたスナップショットの)結果を再生したりする場合に便利です。したがって、例3 これは、セッション番号がフィードバックされた前の呼び出しに基づいて出力するデータを取得する場合です。前述の例1および2など(ここで、パラメーター#4は False でした) 、 でも)。または、以前のデータスナップショットについて単に再レポートしたい場合。

    推奨される使用法は、呼び出し後にセッションデータを削除しないことです。そのため、パラメータ#3は Falseのままにします 、意味は削除しないでください。

    ルーチンはデータにまったく影響を与えません。 Reporting101aのデータのみを変更します データベース。

    出力: ルーチンがコマンドラインの外部(MySQL Workbenchなど)で実行される場合、テーブルラッパー列が出力用に生成されたすべてのテーブル全体を囲みます。列見出しは''(空白の文字列)です。しかし、それでもかなり面倒です。これはOutput1に見られます 下に示された。ただし、コマンドラインを活用する場合は、スイッチ -N -B (列名とバッチモードをスキップ)次の呼び出しなど:

    mysql -uYourDBUser -p -N -B -e "call Reporting101a.describeTables_v3('Sample011',@theOutVar,false,true,'size')" > sampleOut.txt
    

    ...ラップされていない出力を生成します。もっと楽しい。 sampleOut.txtに書き込まれます ファイル。 Output2を参照してください 以下。

    テスト済み: 5.55.6.31 、および5.7.13

    パフォーマンス: CURSORSを使用します プリティプリンティングのために。私は通常、その概念を笑います。しかし、これらはまれな呼び出しであり、おそらく1〜2分は許容できるように思われることを考えると、120テーブルのスキーマのパフォーマンスが10秒未満であることがわかりました。私のテストでは、LinuxはWindowsよりもはるかに高速です。

    2つのストアドプロシージャ(上部のCREATE SCHEMAを含む):

    CREATE SCHEMA IF NOT EXISTS `Reporting101a`;    -- See **Note1**
    
    DROP PROCEDURE IF EXISTS `Reporting101a`.`describeTables_v3`;
    DELIMITER $$
    CREATE DEFINER=`root`@`localhost` PROCEDURE `Reporting101a`.`describeTables_v3`(
        IN pDBName varchar(100), -- the dbname to report table structures
        OUT theSession int, -- OUT parameter for session# assigned
        IN deleteSessionRows BOOL, -- true for delete rows when done from main reporting table for this session#
        IN callTheSecondStoredProc BOOL, -- TRUE = output is from Pretty output in Second Stored Proc. FALSE= not so pretty output
        IN pOrderBy CHAR(20) -- 'ALPHA' OR 'SIZE'. Alphabetical order, or table size order(desc)
    )
    BEGIN
        DECLARE thisTable CHAR(100);
        DECLARE beginDT,endDT DATETIME;
    
        SET beginDT=NOW();
        DROP TEMPORARY TABLE IF EXISTS Reporting101a.tOutput;
        CREATE TEMPORARY TABLE Reporting101a.tOutput
        (   id INT AUTO_INCREMENT PRIMARY KEY,
            tblName VARCHAR(100) NOT NULL,
            ordVal INT NOT NULL,
            cField VARCHAR(100) NOT NULL,
            cType VARCHAR(100) NOT NULL,
            cNull VARCHAR(100) NOT NULL,
            cKey VARCHAR(100) NOT NULL,
            cDefault VARCHAR(100) NULL,
            cExtra VARCHAR(100) NULL,
            cCharSetName VARCHAR(100) NULL,
            cCollName VARCHAR(100) NULL
        );
        DROP TEMPORARY TABLE IF EXISTS Reporting101a.tOutput2;
        CREATE TEMPORARY TABLE Reporting101a.tOutput2
        (   tblName varchar(100) primary key,
            colCount INT NOT NULL,
            cFieldMaxLen INT NOT NULL,
            cTypeMaxLen INT NOT NULL,
            cNullMaxLen INT NOT NULL,
            cKeyMaxLen INT NOT NULL,
            cDefaultMaxLen INT NOT NULL,
            cExtraMaxLen INT NOT NULL,
            cCharSetNameMaxLen INT NOT NULL,
            cCollNameMaxLen INT NOT NULL
        );
    
        INSERT Reporting101a.tOutput(tblName,ordVal,cField,cType,cNull,cKey,cDefault,cExtra,cCharSetName,cCollName)
        SELECT TABLE_NAME,ORDINAL_POSITION,COLUMN_NAME,COLUMN_TYPE,RPAD(IS_NULLABLE,4,' '), 
        RPAD(COLUMN_KEY,3,' '),RPAD(COLUMN_DEFAULT,7,' '),EXTRA,CHARACTER_SET_NAME,COLLATION_NAME
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE table_schema = pDBName ORDER BY table_name,ordinal_position; 
    
        UPDATE Reporting101a.tOutput
        SET cExtra='     '
        WHERE cExtra='';
    
        UPDATE Reporting101a.tOutput
        SET cField=RPAD(cField,5,' ')
        WHERE LENGTH(cField)<5;
    
        UPDATE Reporting101a.tOutput
        SET cCharSetName=RPAD(COALESCE(cCharSetName,''),8,' ')
        WHERE LENGTH(COALESCE(cCharSetName,''))<8;
    
        UPDATE Reporting101a.tOutput
        SET cCollName=RPAD(COALESCE(cCollName,''),9,' ')
        WHERE LENGTH(COALESCE(cCollName,''))<9;
    
        INSERT Reporting101a.tOutput2(tblName,colCount,cFieldMaxLen,cTypeMaxLen,cNullMaxLen,
        cKeyMaxLen,cDefaultMaxLen,cExtraMaxLen,cCharSetNameMaxLen,cCollNameMaxLen) 
        SELECT tblName,COUNT(*),0,0,0,0,0,0,0,0
        FROM Reporting101a.tOutput 
        GROUP BY tblName;
    
        UPDATE tOutput2 t2
        JOIN
        (   SELECT tblName,MAX(LENGTH(cField)) AS mField,MAX(LENGTH(cType)) AS mType,MAX(LENGTH(cNull)) AS mNull,
            IFNULL(MAX(LENGTH(cKey)),0) AS mKey,IFNULL(MAX(LENGTH(cDefault)),0) AS mDefault,IFNULL(MAX(LENGTH(cExtra)),0) AS mExtra,
            IFNULL(MAX(LENGTH(cCharSetName)),0) AS mCharSetName,IFNULL(MAX(LENGTH(cCollName)),0) AS mCollName
            FROM Reporting101a.tOutput
            GROUP BY tblName
        ) x
        ON x.tblName=t2.tblName
        SET t2.cFieldMaxLen=x.mField,t2.cTypeMaxLen=x.mType,cNullMaxLen=x.mNull,cKeyMaxLen=x.mKey,
        cDefaultMaxLen=x.mDefault,cExtraMaxLen=x.mExtra,cCharSetNameMaxLen=x.mCharSetName,cCollNameMaxLen=x.mCollName;
    
        CREATE TABLE IF NOT EXISTS Reporting101a.reportDataSessions
        (   -- For the purpose of safe session auto_inc usage, timings, and rowcount
            -- Please don't delete unless you want the sessions to experience aberrant behavior.
            -- That is, the inability to report on prior sessions run. Which is no big deal.
            sessionId INT AUTO_INCREMENT PRIMARY KEY,
            dbName VARCHAR(100) NOT NULL,
            -- character_set_name VARCHAR(100) NULL,
            -- collation_name VARCHAR(100) NULL,
            creationDT DATETIME NOT NULL,
            partA_BeginDT DATETIME NULL,
            partA_EndDT DATETIME NULL,   -- See the following for fractional seconds:
            partB_BeginDT DATETIME NULL, -- http://dev.mysql.com/doc/refman/5.7/en/fractional-seconds.html
            partB_EndDT DATETIME NULL,
            rowCount INT NULL
        );
    
        CREATE TABLE IF NOT EXISTS Reporting101a.reportDataColumns
        (   sessionId INT NOT NULL,
            tblName VARCHAR(100) NOT NULL,  -- Tablename
            ordVal INT NOT NULL,    -- the "position number" of the Column
            cField VARCHAR(100) NOT NULL,   -- The Column
            cType VARCHAR(100) NOT NULL,    -- Datatype
            cNull VARCHAR(100) NOT NULL,    -- Nullability
            cKey VARCHAR(100) NOT NULL, -- Key info
            cDefault VARCHAR(100) NULL, -- Default value
            cExtra VARCHAR(100) NULL,   -- Extra output
            cCharSetName VARCHAR(100) NULL, -- Default value
            cCollName VARCHAR(100) NULL,    -- Extra output
            colCount INT NOT NULL,  -- the columns here and below are de-normalize data
            cFieldMaxLen INT NOT NULL,
            cTypeMaxLen INT NOT NULL,
            cNullMaxLen INT NOT NULL,
            cKeyMaxLen INT NOT NULL,
            cDefaultMaxLen INT NOT NULL,
            cExtraMaxLen INT NOT NULL,
            cCharSetNameMaxLen INT NOT NULL,
            cCollNameMaxLen INT NOT NULL
        );
    
        CREATE TABLE IF NOT EXISTS Reporting101a.reportDataTables
        (   sessionId INT NOT NULL,
            tblName VARCHAR(100) NOT NULL,  -- tablename
            character_set_name VARCHAR(100) NULL, -- table-level default char set
            collation_name VARCHAR(100) NULL, -- table-level default collation
            rowcount BIGINT NULL, -- rowcount (subject to system refresh, ditto, next column)
            tblSizeMB DECIMAL(14,2) NULL -- in MB
        );
    
        CREATE TABLE IF NOT EXISTS Reporting101a.reportDataDatabases
        (   sessionId INT NOT NULL,
            dbName VARCHAR(100) NOT NULL,   -- Tablename
            character_set_name VARCHAR(100) NULL, -- db-level default char set
            collation_name VARCHAR(100) NULL -- db-level default collation
        );
    
        -- For lack of a better notion, we are calling calls "sessions". The programmer calls the
        -- First Stored Proc, and we call that a session after we get a unique next incrementing number.
        -- That number is the session #. House all output with that as a column value. This allows us to 
        -- move between stored procs, have safe output, have historical snapshots, and retain the data 
        -- via a session # for later use, whatever use.
        INSERT Reporting101a.reportDataSessions(dbName,creationDT) VALUES (pDBName,now());
        SET @mySession=LAST_INSERT_ID(); -- there it is, our session # (read the above paragraph)
    
        INSERT Reporting101a.reportDataColumns(sessionId,tblName,ordVal,cField,cType,cNull,cKey,cDefault,cExtra,cCharSetName,cCollName,
        colCount,cFieldMaxLen,cTypeMaxLen,cNullMaxLen,cKeyMaxLen,cDefaultMaxLen,cExtraMaxLen,cCharSetNameMaxLen,cCollNameMaxLen)    
        SELECT @mySession,t1.tblName,t1.ordVal,t1.cField,t1.cType,t1.cNull,t1.cKey,t1.cDefault,t1.cExtra,t1.cCharSetName,t1.cCollName,
        t2.colCount,t2.cFieldMaxLen,t2.cTypeMaxLen,t2.cNullMaxLen,t2.cKeyMaxLen,t2.cDefaultMaxLen,t2.cExtraMaxLen,t2.cCharSetNameMaxLen,t2.cCollNameMaxLen
        FROM Reporting101a.tOutput t1
        JOIN Reporting101a.tOutput2 t2
        ON t2.tblName=t1.tblName
        ORDER BY t1.tblName,t1.id;
    
        INSERT Reporting101a.reportDataTables(sessionId,tblName,character_set_name,collation_name,rowcount,tblSizeMB)
        SELECT DISTINCT @mySession,tblName,NULL,NULL,NULL,NULL
        FROM Reporting101a.reportDataColumns
        WHERE [email protected];
    
        -- http://dev.mysql.com/doc/refman/5.7/en/collation-character-set-applicability-table.html
        -- TLDR; A collation can map to a character set
        UPDATE Reporting101a.reportDataTables rdt
        JOIN INFORMATION_SCHEMA.`TABLES` ist
        ON ist.TABLE_SCHEMA=pDBName AND ist.TABLE_NAME=rdt.tblName
        JOIN INFORMATION_SCHEMA.`COLLATION_CHARACTER_SET_APPLICABILITY` isccsa
        ON isccsa.COLLATION_NAME=ist.TABLE_COLLATION
        SET rdt.character_set_name=isccsa.CHARACTER_SET_NAME,rdt.collation_name=isccsa.COLLATION_NAME,
        rdt.rowcount=ist.TABLE_ROWS,rdt.tblSizeMB=round(((ist.data_length+ist.index_length) / 1048576), 2)
        WHERE [email protected];
    
        INSERT Reporting101a.reportDataDatabases(sessionId,dbName,character_set_name,collation_name)
        SELECT @mySession,pDBName,DEFAULT_CHARACTER_SET_NAME,DEFAULT_COLLATION_NAME
        FROM INFORMATION_SCHEMA.SCHEMATA
        WHERE schema_name = pDBName;
    
        DROP TEMPORARY TABLE Reporting101a.tOutput;
        DROP TEMPORARY TABLE Reporting101a.tOutput2;
        SET [email protected]; -- the OUT var that came in as a parameter
        SET endDT=NOW();
        UPDATE Reporting101a.reportDataSessions 
        SET partA_BeginDT=beginDT,partA_EndDT=endDT 
        WHERE [email protected];
        -- ***************************************************************************
        -- ***************************************************************************
        -- Label "Some_Sort_of_Output":
        IF callTheSecondStoredProc=TRUE THEN
            -- The caller says to call the second stored proc (for Pretty Printing)
            -- This will generate output similar to `DESCRIBE myTable`
            -- But remember, it will do it  for EVERY table in referenced database
            CALL Reporting101a.`Print_Tables_Like_Describe`(@mySession,pOrderBy);
            -- The above call just gave you output.
        ELSE
            -- The caller chose to not auto call the Pretty Printing second stored procedure.
            -- Note, the caller can easily call it right after using the OUT parameter.
            -- So our output will be a resultset of out reportDataColumns table for this session #
            IF pOrderBy!='size' THEN
                -- Order by Alpha for any parameter except 'size'
                SELECT * 
                FROM Reporting101a.reportDataColumns 
                WHERE [email protected]
                ORDER BY tblName,ordVal;
            ELSE
                -- Order By size DESC
                SELECT rdc.* 
                FROM Reporting101a.reportDataTables rdt
                JOIN Reporting101a.reportDataColumns rdc 
                ON rdc.tblName=rdt.tblName and rdc.sessionId=rdt.sessionId
                WHERE [email protected]
                ORDER BY rdt.tblSizeMB DESC,rdc.tblName,rdc.ordVal;
            END IF;
        END IF;
        -- ***************************************************************************
        -- ***************************************************************************
    
        IF deleteSessionRows=TRUE THEN
            -- The caller says output rows are NOT needed at this point. Delete them.
            -- Note, if this boolean comes in TRUE, you can't call Pretty Printing
            -- second stored procedure with the session # because the data is gone.
            --
            -- Regardless, you are getting something back from "Some_Sort_of_Output" above.
            DELETE FROM Reporting101a.reportDataColumns
            WHERE [email protected];
    
            DELETE FROM Reporting101a.reportDataTables
            WHERE [email protected];
    
            -- Do not delete the row from the Sessions table for now (you can, I'm not atm)
        END IF;
    END$$
    DELIMITER ;
    
    -- *****************************************************************
    -- *****************************************************************
    -- *****************************************************************
    
    DROP PROCEDURE IF EXISTS `Reporting101a`.`Print_Tables_Like_Describe`;
    DELIMITER $$
    CREATE DEFINER=`root`@`localhost` PROCEDURE `Reporting101a`.`Print_Tables_Like_Describe`(
        IN pSessionId INT,
        IN pOrderBy CHAR(20) -- 'size' or 'alpha' (see CURSORs below). Size means Tablesize (see ____).
    )
    BEGIN
        -- Please note: CURSOR stuff must come last in DECLAREs, else "Error 1337: Variable or condition decl aft curs" 
        DECLARE beginDT,EndDT DATETIME; 
        DECLARE done INT DEFAULT FALSE;
        DECLARE curTable VARCHAR(100) DEFAULT '';
        DECLARE bFirst BOOL DEFAULT TRUE;
        DECLARE lv_dbName,CharSetName,CollationName,someClueToCaller VARCHAR(100);
        DECLARE lv_rowCount,lineCount INT;
        DECLARE theSize DECIMAL(14,2);
        DECLARE lv_sessionDT DATETIME;
        DECLARE lv_tblName,lv_cField,lv_cType,lv_cNull,lv_cKey,lv_cDefault,lv_cExtra,lv_cCharSetName,lv_cCollName VARCHAR(100);
        DECLARE lv_ordVal,lv_colCount,lv_cFieldMaxLen,lv_cTypeMaxLen,lv_cNullMaxLen,lv_cKeyMaxLen,
        lv_cDefaultMaxLen,lv_cExtraMaxLen,lv_cCharSetNameMaxLen,lv_cCollNameMaxLen INT;
        -- -------------------------------------------------------------------------------------------------------------------
        -- The below cursor is in Alphabetical Ascending order
        DECLARE curAlpha CURSOR FOR SELECT tblName,ordVal,cField,cType,cNull,cKey,cDefault,cExtra,cCharSetName,cCollName,
        colCount,cFieldMaxLen,cTypeMaxLen,cNullMaxLen,cKeyMaxLen,cDefaultMaxLen,cExtraMaxLen,cCharSetNameMaxLen,cCollNameMaxLen
        FROM Reporting101a.reportDataColumns
        WHERE rdt.sessionId=pSessionId
        ORDER BY tblName,ordVal; -- ascending order by tablename then the ordinal position of each column (1..n)
    
        -- The below cursor is in Tablesize Descending order, followed by tablename + ordinal position ascending
        DECLARE curSize CURSOR FOR SELECT rdc.tblName,rdc.ordVal,rdc.cField,rdc.cType,rdc.cNull,rdc.cKey,rdc.cDefault,
        rdc.cExtra,rdc.cCharSetName,rdc.cCollName,rdc.colCount,rdc.cFieldMaxLen,rdc.cTypeMaxLen,rdc.cNullMaxLen,
        rdc.cKeyMaxLen,rdc.cDefaultMaxLen,rdc.cExtraMaxLen,rdc.cCharSetNameMaxLen,rdc.cCollNameMaxLen
        FROM Reporting101a.reportDataTables rdt
        JOIN Reporting101a.reportDataColumns rdc
        ON rdc.tblName=rdt.tblName and rdc.sessionId=rdt.sessionId
        WHERE rdt.sessionId=pSessionId
        ORDER BY rdt.tblSizeMB DESC,rdc.tblName,rdc.ordVal; -- tablesize desc, then tablename + ordinal position ascending
    
        -- What is the Ordinal Position? Simply 1..n as saved in the db 
        -- (see ORDINAL_POSITION in INFORMATION_SCHEMA.COLUMNS)
        --
        -- If it is terribly bothersome, then look into 
        -- "ALTER TABLE" and use FIRST or AFTER   .. :)
    
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
        -- Please note in the above, CURSOR stuff MUST come LAST else "Error 1337: Variable or condition decl aft curs" 
        -- -------------------------------------------------------------------------------------------------------------------
        SET beginDT=NOW();
        SET lineCount=0;
        CREATE TABLE IF NOT EXISTS Reporting101a.reportOutput
        (   lineNum INT AUTO_INCREMENT PRIMARY KEY,
            sessionId INT NOT NULL,
            lineOut varchar(200) NOT NULL
        );
    
        DELETE FROM Reporting101a.reportOutput WHERE sessionId=pSessionId; -- cleans up a prior run with this session#
    
        IF pOrderBy!='size' THEN
            OPEN curAlpha; -- we are in using the Alphabetical Cursor (includes typos from caller for the sort column)
        ELSE
            OPEN curSize; -- we are in using the Tablesize Cursor
        END IF;
    
        -- **Place004** (Top-most output, Session #, then get top-level database info, there is not much of it)
        -- Here is the importance of it though: it documents the state of things at that point in time
        -- And it allows for reporting later by using that Session # (so that is why a Session # should hang out and remain)
        -- So, a snapshot. You don't even need to print and use the output now. You can have it for later. To compare.
        SELECT creationDT INTO lv_sessionDT FROM Reporting101a.reportDataSessions WHERE sessionId=pSessionId;
    
        SET someClueToCaller='Typo from caller, using Alphabetical';
        IF pOrderBy='size' THEN
            SET someClueToCaller='table size DESC';
        END IF;
        IF pOrderBy='alpha' THEN
            SET someClueToCaller='tablename alphabetical';
        END IF;
        INSERT Reporting101a.reportOutput(sessionId,lineOut)
        SELECT pSessionId,CONCAT('Session: ', pSessionId, ', Date:',lv_sessionDT,' , SortOrder: ',someClueToCaller);
    
        INSERT Reporting101a.reportOutput(sessionId,lineOut) VALUES (pSessionId,''); -- blank line
    
        SELECT dbName,character_set_name,collation_name INTO lv_dbName,CharSetName,CollationName
        FROM Reporting101a.reportDataDatabases
        WHERE sessionId=pSessionId;
    
        INSERT Reporting101a.reportOutput(sessionId,lineOut)
        SELECT pSessionId,CONCAT('Database: ', lv_dbname, ' (CharSet=', COALESCE(CharSetName,''), ', Collation=', COALESCE(CollationName,''), ')');
    
        INSERT Reporting101a.reportOutput(sessionId,lineOut) VALUES (pSessionId,''); -- blank line
        -- end **Place004** ----------------------------------------------------------------------
    
    
        read_loop: LOOP
            IF pOrderBy!='size' THEN
                FETCH curAlpha INTO lv_tblName,lv_ordVal,lv_cField,lv_cType,lv_cNull,lv_cKey,lv_cDefault,lv_cExtra,lv_cCharSetName,
                lv_cCollName,lv_colCount,lv_cFieldMaxLen,lv_cTypeMaxLen,lv_cNullMaxLen,lv_cKeyMaxLen,lv_cDefaultMaxLen,
                lv_cExtraMaxLen,lv_cCharSetNameMaxLen,lv_cCollNameMaxLen ;
            ELSE
                FETCH curSize INTO lv_tblName,lv_ordVal,lv_cField,lv_cType,lv_cNull,lv_cKey,lv_cDefault,lv_cExtra,lv_cCharSetName,
                lv_cCollName,lv_colCount,lv_cFieldMaxLen,lv_cTypeMaxLen,lv_cNullMaxLen,lv_cKeyMaxLen,lv_cDefaultMaxLen,
                lv_cExtraMaxLen,lv_cCharSetNameMaxLen,lv_cCollNameMaxLen ;
            END IF;
            IF done THEN
                LEAVE read_loop;
            END IF;
            IF lv_tblName<>curTable THEN -- **Place006**, "the IF"
                -- We stumbled into a "This is a New table condition (different table)
                -- So we need to create the New Chunk Header Info (also get table-level info like rowcount etc ie **Place7** below)
                -- (as opposed to just displaying the next column info on a table we were already working with)
                IF bFirst=FALSE THEN
                    INSERT Reporting101a.reportOutput(sessionId,lineOut)
                    SELECT pSessionId,''; -- Insert a blank line between tables (but not the first time)
                ELSE
                    SET bFirst=FALSE;
                END IF;
    
                -- **Place007** (get top-level table info, there is not much of it, just, like, rowcount, charset, collation)
                SELECT rowcount,character_set_name,collation_name,tblSizeMB INTO lv_rowCount,CharSetName,CollationName,theSize
                FROM Reporting101a.reportDataTables
                WHERE sessionId=pSessionId AND tblName=lv_tblName;
    
                INSERT Reporting101a.reportOutput(sessionId,lineOut)
                SELECT pSessionId,CONCAT(lv_tblName,' (rowcount=',ifnull(lv_rowCount,0),') (Size=',theSize,'MB) (CharSet=',COALESCE(CharSetName,''), ', Collation=',COALESCE(CollationName,''),')');
                -- end **Place007** ----------------------------------------------------------------------
    
    
                INSERT Reporting101a.reportOutput(sessionId,lineOut)
                SELECT pSessionId,CONCAT('+-', 
                    REPEAT('-',GREATEST(5,lv_cFieldMaxLen)),  '-+-',
                    REPEAT('-',GREATEST(4,lv_cTypeMaxLen)), '-+-',
                    REPEAT('-',GREATEST(4,lv_cNullMaxLen)), '-+-',
                    REPEAT('-',GREATEST(3,lv_cKeyMaxLen)), '-+-',
                    REPEAT('-',GREATEST(7,lv_cDefaultMaxLen)), '-+-',
                    REPEAT('-',GREATEST(5,lv_cExtraMaxLen)), '-+-',
                    REPEAT('-',GREATEST(8,lv_cCharSetNameMaxLen)),'-+-',
                    REPEAT('-',GREATEST(5,lv_cCollNameMaxLen)), '-+');
    
                SET @dashLineNumRow=LAST_INSERT_ID(); -- **Place008**: Save this row id so we can use it again in one sec
    
                INSERT Reporting101a.reportOutput(sessionId,lineOut)
                SELECT pSessionId,CONCAT('| ', 
                    'Field',
                    REPEAT(' ',GREATEST(0,lv_cFieldMaxLen-5)),  ' | ',
                    'Type',
                    REPEAT(' ',GREATEST(0,lv_cTypeMaxLen-4)),   ' | ',
                    'Null',
                    REPEAT(' ',GREATEST(0,lv_cNullMaxLen-4)),   ' | ',
                    'Key',
                    REPEAT(' ',GREATEST(0,lv_cKeyMaxLen-3)),    ' | ',
                    'Default',
                    REPEAT(' ',GREATEST(0,lv_cDefaultMaxLen-7)),    ' | ',
                    'Extra',
                    REPEAT(' ',GREATEST(0,lv_cExtraMaxLen-5)),  ' | ',
                    'Char Set',
                    REPEAT(' ',GREATEST(0,lv_cCharSetNameMaxLen-8)),    ' | ',
                    'Collation',
                    REPEAT(' ',GREATEST(0,lv_cCollNameMaxLen-9)),   ' |');
    
                INSERT Reporting101a.reportOutput(sessionId,lineOut)
                SELECT pSessionId,lineOut FROM Reporting101a.reportOutput
                WHERE [email protected]; -- related to **Place008** above (just repeat it to close-off header)
    
                SET curTable=lv_tblName; -- set the variable which is our flag for Next/New/Different table (related: **Place006** above)
            END IF;
    
            -- The below is the generic insert for a column's info
            INSERT Reporting101a.reportOutput(sessionId,lineOut)
            SELECT pSessionId,
                CONCAT('| ', 
                lv_cField,
                COALESCE(REPEAT(' ',GREATEST(0,lv_cFieldMaxLen-LENGTH(lv_cField))),''),' | ',
                COALESCE(lv_cType,''),
                COALESCE(REPEAT(' ',GREATEST(0,lv_cTypeMaxLen-LENGTH(lv_cType))),''),' | ',
                COALESCE(lv_cNull,''),
                COALESCE(REPEAT(' ',GREATEST(0,lv_cNullMaxLen-LENGTH(lv_cNull))),''),' | ',
                COALESCE(lv_cKey,'   '),
                COALESCE(REPEAT(' ',GREATEST(0,lv_cKeyMaxLen-LENGTH(lv_cKey))),''),' | ',
                COALESCE(lv_cDefault,'       '),
                COALESCE(REPEAT(' ',GREATEST(0,lv_cDefaultMaxLen-LENGTH(lv_cDefault))),''),' | ',
                COALESCE(lv_cExtra,'     '),
                COALESCE(REPEAT(' ',GREATEST(0,lv_cExtraMaxLen-LENGTH(lv_cExtra))),''),' | ',
                lv_cCharSetName, 
                REPEAT(' ',GREATEST(0,lv_cCharSetNameMaxLen-LENGTH(lv_cCharSetName))),' | ',
                lv_cCollName,
                REPEAT(' ',GREATEST(0,lv_cCollNameMaxLen-LENGTH(lv_cCollName))),' |');
            SET lineCount=lineCount+1; -- increment only for column rows not separator rows
            INSERT Reporting101a.reportOutput(sessionId,lineOut)
            SELECT pSessionId,lineOut
            FROM Reporting101a.reportOutput
            WHERE [email protected];
        END LOOP;
        IF pOrderBy!='size' THEN
            CLOSE curAlpha;
        ELSE 
            CLOSE curSize;
        END IF;
    
        SET endDT=NOW();
    
        UPDATE Reporting101a.reportDataSessions 
        SET partB_BeginDT=beginDT,partB_EndDT=endDT,rowCount=lineCount
        WHERE sessionId=pSessionId;
    
        SELECT lineOut AS '' from Reporting101a.reportOutput WHERE sessionId=pSessionId ORDER BY lineNum;
        -- Note: The whole outer box wrapper is suppressed (which is cool) if we perform a
        --
        -- OSPrompt> mysql -N -B -u UserName -p -e "call Reporting101a.describeTables_v3('stackoverflow',@theOutVar,false,true,'size')"
        --
        -- That above -N -B suppresses column info (-N), ... (-B) keeps the output left aligned and is Batch mode
        -- I understand (-N), but without (-B) the alignment goes right-aligned
        -- Regardless, it allows us to perform what would appear to 
        -- be merely PRINT statements, if you will. No outer box wrapper in output.
    END$$
    DELIMITER ;
    

    Output1(ラッピング/包含外部テーブルを表示)。 2つの黄色の蛍光ペンはテーブル名です。

    Output2(-N -Bを使用したコマンドライン スイッチ)外側のラッピングテーブルを取り外します。上記の出力の例を参照してください 使用法のセクション。効果的には、MySQLのコマンドのようなPRINTを可能にします。




    1. MySQLクエリの問題

    2. mysqlの同等のデータ型

    3. MySQL暗号化/機密データの保存、

    4. OracleのCOMPOSE()関数