Показать все таблицы. Опишите подобную функциональность

Как я могу отобразить все таблицы в базе данных, похожие на вывод, какDESCRIBE myTable, Добавление функциональности для:

Все таблицы одновременноразмер таблицыНабор символов и информация о сопоставленииВозможности сортировки

Замечания:DESCRIBE Вывод прост и для одной таблицы за раз.

Редактировать:

Хороший отзыв от Рика Джеймса. Я был в растерянности и нуждался в этом мозговом штурме.

Если кто-то хочет добавить функциональность (к моему самоответу), такую ​​как строка с отступом внизу каждой таблицы для

Индексы (возможно, 1 строка на индекс, показывающая имена и имена столбцов, разделенные запятойКоличество элементов в этой строке индекса вышеОграничения внешнего ключаВсе остальное, что есть у вас, может помочь вашим сверстникам.Концептуально иметь весь этот блок, называемый «Расширенная информация», и переключатель (параметр) для Yay или Nay для его создания. Если 'N', то не производите это.

Я был бы очень доволен. Естественно, эта информация не будет зависеть от заголовков столбцов, уже показанных мной в ответе на свой вопрос. Таким образом, сразу приходит на ум какой-то визуальный элемент, такой как отступ, а не то, чтобы он был частью таблицы. Грубый вывод в порядке.

Рассмотрите следующие грубые заметки, которые могут оказаться полезными:

create schema x99;
use x99;

create table parent
(   -- assume your have only one parent, ok bad example, it's early
    id int auto_increment primary key,
    fullName varchar(100) not null
)ENGINE=InnoDB;

-- drop table child;
create table child
(   id int auto_increment primary key,
    fullName varchar(100) not null,
    myParent int not null,
    CONSTRAINT `mommy_daddy` FOREIGN KEY (myParent) REFERENCES parent(id)
        ON DELETE CASCADE ON UPDATE CASCADE     
)ENGINE=InnoDB;

create table t3
(   id INT AUTO_INCREMENT PRIMARY KEY,
    myD DATE NOT NULL,
    myI INT NOT NULL,
    KEY `t3_001` (myD,myI)
);

create table t4
(   someCode CHAR(4) PRIMARY KEY,
    codeDescr VARCHAR(500) NOT NULL
);

create table t5
(   id INT AUTO_INCREMENT PRIMARY KEY,
    theCode CHAR(4) NOT NULL,
    d1 DATE NOT NULL,
    i1 INT NOT NULL,
    someOther DATETIME NOT NULL,
    FOREIGN KEY `cd_2_t4` (theCode) REFERENCES t4(someCode),
    FOREIGN KEY `cd_2_t3` (d1,i1) REFERENCES t3(myD,myI)
);

-- The below 2 lines are merely to show cardinality which I am sure is
-- read from INFO SCHEMA too
show indexes in child; -- to pick up cardinality (or from INFO SCHEMA)
show indexes in t5; -- ditto
-- So, I am not suggesting to actually call "show indexes"


-- http://dev.mysql.com/doc/refman/5.7/en/key-column-usage-table.html
-- James Goatcher
SELECT CONCAT( table_name, '.', 
column_name, ' -> ', 
referenced_table_name, '.', 
referenced_column_name ) AS list_of_fks 
FROM information_schema.KEY_COLUMN_USAGE 
WHERE REFERENCED_TABLE_SCHEMA = 'x99' 
AND REFERENCED_TABLE_NAME is not null 
ORDER BY TABLE_NAME, COLUMN_NAME; 
+-----------------------------+
| list_of_fks                 |
+-----------------------------+
| child.myParent -> parent.id |
| t5.d1 -> t3.myD             |
| t5.i1 -> t3.myI             |
| t5.theCode -> t4.someCode   |
+-----------------------------+

Despite the output suggested by James Goatcher on that Webpage, 
perhaps what would look better under table t5 as 2 lines:

t5.d1,i1 -> t3.myD,myI              <----- That there would be swell
t5.theCode -> t4.someCode

-- You may make the assumption that all tables are in the same schema
-- If they aren't and it blows up that is fine

drop schema x99;

Я хотел бы наградить эту награду.

 Rick James03 авг. 2016 г., 21:55
Обратите внимание, чтоDESCRIBE неполно, когда дело доходит до составных индексов, движка и т. д.
 Rick James03 авг. 2016 г., 22:14
Какова целевая аудитория? Я вообще доволен наборомSHOW CREATE TABLE.
 Drew03 авг. 2016 г., 21:34
Я ищу улучшения, рецензирование, другие предложения.
 Drew03 авг. 2016 г., 22:22
@RickJames Я ищу мозговой штурм именно этого. Люди, которые ищут информацию в таблице (для всех таблиц или, возможно, вIN оговорка, всеэти таблицы) для получения информации, помогающей в отладке или других попытках программирования, таких как ограничения внешнего ключа

Ответы на вопрос(1)

Это распространяется на ответ, данныйВот, Он добавляет столбцы «Набор символов» и «Сопоставление», а также на уровне базы данных и таблицы. Включена сортировка по двум вариантам: по алфавиту и по размеру таблицы, рассчитанная аналогичноВот, Я все еще думаю, что эта концепция нуждается в экспертной оценке. Роландо на DBAВот показывал метод, и Рик Джеймс прокомментировал. Это не простой расчет и никогда не включает нестатические данные, такие какTEXT а такжеBLOBs. Поэтому не стесняйтесь улучшать этот расчет и делиться им. Независимо от этого таблицы обычно возвращаются в желаемом порядке сортировки, если по размеру. Я не даю никаких гарантий в отношении его точности, поскольку это касается размера файла InnoDB.

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

Сессии: Это опирается на концепцию сеанса, который является просто примером того, как вы вызываете подпрограммы. Думай о них какмоментальные снимки это может быть доступ позже. Данные в этот момент времени содержатся в снимке сеанса. Может быть полезно, когда вы меняете таблицы. В частности, сопоставление. Да, и в отношении сопоставления ограничения внешнего ключа часто терпят неудачу из-за неправильных настроек сопоставления, так как разработчики вырезают и вставляют код из Интернета (набор символов на уровне таблицы и на уровне столбца и несоответствия сопоставления). Вот почему я бросил это в эту версию.

Процедуры живут в базе данныхReporting101a в нем размещены две хранимые процедуры и несколько вспомогательных таблиц (почти все на основе сеансов). Около 5 таблиц.

Примеры вызова:

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

УвидетьПримечаниеЗначок

Параметры (1-й сохраненный процесс):

Имя базы данных для описания всех таблиц.INT OUT параметр для хранения сессии #логическое значение: хотите ли вы удалить данные из таблицы отчетов в концеboolean: мы должны автоматически вызывать хранимую процедуру Pretty Printing, которая генерируетdescribe-подобный выход.Порядок сортировки: «размер» или «альфа». Фактически, все что угодно, кроме «размера», приведет к «альфе».

Параметры (Pretty Printing Stored Proc):

Номер сеанса предыдущего сохраненного снимка.Порядок сортировки, как указано выше.

Код довольно хорошо документирован, если не считать превращение его в 600 строк кода против 400.

Процедуры являются автономными и ссылаются на себя вReporting101a база данных. Так что звоните им явно откуда угодно.

ПримечаниеЗначок: Что касается приведенных выше примеров:Ex. 1 и 2 как похожий, просто другой порядок сортировки. Это ваш обычный способ использовать его только содин вызов. Размер таблицы всегда отображается рядом с именем таблицы. Сортируется только по размерунисходящий в теме. С 4-м параметром какПравдав конце он автоматически вызывает процесс «Pretty Printing Stored Proc». В противном случае выводится простой набор результатов Джейн.@theOutVar будет записано в том виде, в котором оно представляет созданный Session #. Это полезно для ручного вызова хранимой процедуры Pretty Printing вскоре после этого, вклинивания одной из ваших подпрограмм и использования данных или воспроизведения результатов через несколько месяцев (из замороженного снимка). Так,Ex. 3 это тот случай, когда вы хотите получить данные для вывода на основе предварительного вызова, после того как был возвращен номер сеанса. Например, в упомянутых выше примерах 1 и 2 (где параметр # 4 был быЛожь, тем не мение). Или, если вы просто хотите повторно отчитаться о предыдущем снимке данных.

Рекомендуемое использование - не удалять данные сеанса после вызовов. Таким образом, оставьте параметр № 3 какЛожьЗначит не удаляй.

Подпрограммы никак не влияют на ваши данные. Это только изменяет данные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 файл. УвидетьВыход2 ниже.

Проверено на: 5.5, 5.6.31, а также5.7.13.

Спектакль: Оно используетCURSORS для милой печати. Я обычно смеюсь над концепцией. Но, учитывая, что это редкие вызовы и, возможно, одна или две минуты показались бы приемлемыми, я с удовлетворением обнаружил, что производительность составляет менее 10 секунд для схемы со 120 таблицами. В моем тестировании Linux намного быстрее, чем Windows.

Две хранимые процедуры (включая 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 ;

Выход 1 (показывает упаковку / содержащую внешнюю таблицу). Две желтые части подсветки являются именами таблиц.

Выход 2 (использование командной строки-N -B выключатели), которые удаляют внешний упаковочный стол. Смотрите пример выше вВыход раздел для использования. Эффективно позволяет печатать как команды в MySQL.

 100011101 авг. 2016 г., 10:07
Все произошло в одно мгновение! :п
 Rick James03 авг. 2016 г., 22:07
Предлагаемое дополнение:COMMENTs.
 Drew03 авг. 2016 г., 22:15
@RickJames Генерирует вывод для 120 таблиц за 8 секунд на дробном VPS на aws EC2.
 Rick James03 авг. 2016 г., 22:04
Data_length + Index_length дает точный «размер» диска таблицы InnoDB. Мне не хватает одного из ваших ранних замечаний о неточных размерах.
 Rick James03 авг. 2016 г., 22:09
Предлагаемое дополнение: Информация о разделах. (У меня есть PHP-код для такого.) То же самое для разбивки индекса BTree (хорошо - это сильно отличается между Percona и Oracle).
 Drew03 авг. 2016 г., 22:26
@RickJames это звучит как отличные идеи. Кто-то может это загнать, если захочет.
 Rick James03 авг. 2016 г., 21:56
Если у вас много таблиц, запросы могут быть медленными. Они должны эффективно открывать каждый стол. (5.8 встроенный словарь данных решит это.)
 JAL03 авг. 2016 г., 22:38
@RickJames Пользователь, разместивший награду, не может присудить ее себе. ПроверитьБаунти пост в FAQ.
 Rick James03 авг. 2016 г., 22:07
Предлагаемое дополнение:Tablespace: file_per_table File_format: Antelope Row_format: Compact
 Rick James03 авг. 2016 г., 22:13
Сохраненные подпрограммы, триггеры, представления, внешние ключи, ограничения разрешений?
 Drew05 авг. 2016 г., 07:19
@middlestump Я сделал ответ на свой вопрос, потом понял, что еще многое предстоит сделать
 Rick James03 авг. 2016 г., 22:10
Предлагаемое дополнение: индекс мощности
 Rick James03 авг. 2016 г., 21:58
Имейте в виду, что количество строк является приблизительным для таблиц InnoDB.
 middlestump05 авг. 2016 г., 08:54
С собственным ответом получаю высокие голоса. (Я тоже голосовал, прежде чем понял). Никто не собирается отвечать. Поместите абзац о собственном ответе в вопросе большим жирным шрифтом, чтобы было понятно, что вы хотите другой ответ
 Drew03 авг. 2016 г., 22:39
@RickJames, почему я должен вручить это себе?

Ваш ответ на вопрос