Converti lo schema MySQL in Github Wiki?

Sto documentando un progetto usando le pagine Wiki di GitHub e ora vorrei esportare lo schema del database MySQL in formato markdown. C’è un modo per convertire l’output CLI in GitHub Wiki md? Idealmente come tavoli.

Il mio risultato è simile a questo:

inserisci la descrizione dell'immagine qui

Questo codice è piuttosto lungo. Chiedo scusa. Consiste di due stored procedure. Potresti essere soddisfatto mentre corri solo il primo. Il secondo utilizza l’output dal primo (i dati la prima a sinistra nelle tabelle). Potresti anche voler combinare il codice in uno. Ma li ho tenuti separati. Il secondo proc memorizzato produce l’output per describe myTable . Ma lo esegue per TUTTE le tabelle nel database che desideri tale output.

Si utilizza questo passando un parametro (stringa) per il database su cui eseguire il report.

Creo un database separato e il codice fa esplicitamente riferimento alle tabelle nel database in base al nome. Pertanto, se si dispone dei privilegi EXECUTE per questa procedura memorizzata, è ansible eseguirla da qualsiasi database corrente. Quindi, come test semplice, non impostare il database di report come database corrente e chiamare semplicemente la procedura memorizzata per nome (qualificato con il nome di reporting db). Questo è tutto mostrato nel blocco Test qui sotto.

Due stored procedure

 CREATE SCHEMA Reporting101a; -- See **Note1** DROP PROCEDURE IF EXISTS `Reporting101a`.`describeTables_v2a`; DELIMITER $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `Reporting101a`.`describeTables_v2a`( IN dbName 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 ) BEGIN DECLARE thisTable CHAR(100); 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 ); 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 ); INSERT Reporting101a.tOutput(tblName,ordVal,cField,cType,cNull,cKey,cDefault,cExtra) SELECT TABLE_NAME,ORDINAL_POSITION,COLUMN_NAME AS Field, COLUMN_TYPE AS TYPE, RPAD(IS_NULLABLE,4,' ') AS 'Null', RPAD(COLUMN_KEY,3,' ') AS 'Key',RPAD(COLUMN_DEFAULT,7,' ') AS 'DEFAULT',EXTRA AS Extra FROM information_schema.columns WHERE table_schema = dbName ORDER BY table_name,ordinal_position; -- select * from information_schema.columns WHERE table_schema = '57security' 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; INSERT Reporting101a.tOutput2(tblName,colCount,cFieldMaxLen,cTypeMaxLen,cNullMaxLen,cKeyMaxLen,cDefaultMaxLen,cExtraMaxLen) SELECT tblName,COUNT(*),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 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; -- DROP TABLE Reporting101a.reportDataDefsSession; -- useful for quick change of structure of table -- note, keep above drop call remmed out ! Just use it for quick tweaks to structure CREATE TABLE IF NOT EXISTS Reporting101a.reportDataDefsSession ( -- for the sole purpose of safe session auto_inc usage -- Please don't delete unless you want the sessions to experience aberant behavior sessionId INT AUTO_INCREMENT PRIMARY KEY, dummy CHAR(1) NOT NULL, creationDT datetime not null ); CREATE TABLE IF NOT EXISTS Reporting101a.reportDataDefs ( 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 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 ); -- 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.reportDataDefsSession(dummy,creationDT) VALUES ('X',now()); SET @mySession=LAST_INSERT_ID(); -- there it is, our session # (read the above paragraph) INSERT Reporting101a.reportDataDefs(sessionId,tblName,ordVal,cField,cType,cNull,cKey,cDefault,cExtra, colCount,cFieldMaxLen,cTypeMaxLen,cNullMaxLen,cKeyMaxLen,cDefaultMaxLen,cExtraMaxLen) SELECT @mySession,t1.tblName,t1.ordVal,t1.cField,t1.cType,t1.cNull,t1.cKey,t1.cDefault,t1.cExtra, t2.colCount,t2.cFieldMaxLen,t2.cTypeMaxLen,t2.cNullMaxLen,t2.cKeyMaxLen,t2.cDefaultMaxLen,t2.cExtraMaxLen FROM Reporting101a.tOutput t1 JOIN Reporting101a.tOutput2 t2 ON t2.tblName=t1.tblName ORDER BY t1.tblName,t1.id; DROP TEMPORARY TABLE Reporting101a.tOutput; DROP TEMPORARY TABLE Reporting101a.tOutput2; SET theSession=@mySession; -- the OUT var that came in as a parameter -- *************************************************************************** -- *************************************************************************** -- 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); -- 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 reportDataDefs table for this session # SELECT * FROM Reporting101a.reportDataDefs WHERE sessionId=@mySession ORDER BY tblName,ordVal; 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.reportDataDefs WHERE sessionId=@mySession; END IF; END$$ DELIMITER ; DROP PROCEDURE IF EXISTS `Reporting101a`.`Print_Tables_Like_Describe`; DELIMITER $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `Reporting101a`.`Print_Tables_Like_Describe`( pSessionId INT ) BEGIN DECLARE done INT DEFAULT FALSE; DECLARE curTable VARCHAR(100) DEFAULT ''; DECLARE bFirst BOOL DEFAULT TRUE; DECLARE lv_tblName,lv_cField,lv_cType,lv_cNull,lv_cKey,lv_cDefault,lv_cExtra VARCHAR(100); DECLARE lv_ordVal,lv_colCount,lv_cFieldMaxLen,lv_cTypeMaxLen,lv_cNullMaxLen,lv_cKeyMaxLen,lv_cDefaultMaxLen,lv_cExtraMaxLen INT; DECLARE cur1 CURSOR FOR SELECT tblName,ordVal,cField,cType,cNull,cKey,cDefault,cExtra, colCount,cFieldMaxLen,cTypeMaxLen,cNullMaxLen,cKeyMaxLen,cDefaultMaxLen,cExtraMaxLen FROM Reporting101a.reportDataDefs WHERE sessionId=pSessionId ORDER BY tblName,ordVal; 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" CREATE TABLE IF NOT EXISTS Reporting101a.reportOutput ( lineNum INT AUTO_INCREMENT PRIMARY KEY, sessionId INT NOT NULL, lineOut varchar(100) NOT NULL ); -- INSERT Reporting101a.reportOutput(sessionId,lineOut) -- SELECT -- SET curTable=''; DELETE FROM Reporting101a.reportOutput WHERE sessionId=pSessionId; OPEN cur1; read_loop: LOOP FETCH cur1 INTO lv_tblName,lv_ordVal,lv_cField,lv_cType,lv_cNull,lv_cKey,lv_cDefault,lv_cExtra, lv_colCount,lv_cFieldMaxLen,lv_cTypeMaxLen,lv_cNullMaxLen,lv_cKeyMaxLen,lv_cDefaultMaxLen,lv_cExtraMaxLen ; IF done THEN LEAVE read_loop; END IF; IF lv_tblName<>curTable THEN IF bFirst=FALSE THEN INSERT Reporting101a.reportOutput(sessionId,lineOut) SELECT pSessionId,''; ELSE SET bFirst=FALSE; END IF; INSERT Reporting101a.reportOutput(sessionId,lineOut) SELECT pSessionId,lv_tblName; 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)), '-+'); SET @dashLineNumRow=LAST_INSERT_ID(); 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)), ' |'); INSERT Reporting101a.reportOutput(sessionId,lineOut) SELECT pSessionId,lineOut FROM Reporting101a.reportOutput WHERE lineNum=@dashLineNumRow; -- SELECT * FROM Reporting101a.reportDataDefs WHERE sessionId=24; SET curTable=lv_tblName; END IF; INSERT Reporting101a.reportOutput(sessionId,lineOut) SELECT pSessionId, CONCAT('| ', COALESCE(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))),''),' |'); INSERT Reporting101a.reportOutput(sessionId,lineOut) SELECT pSessionId,lineOut FROM Reporting101a.reportOutput WHERE lineNum=@dashLineNumRow; END LOOP; CLOSE cur1; select lineOut as '' from Reporting101a.reportOutput where sessionId=pSessionId order by lineNum; END$$ DELIMITER ; 

Test

Test:

 -- See **Note2** SET @theOutVar =-1; -- A variable used as the OUT variable below -- See **Note3** -- Note: with `TRUE` as the 4th parameter, this is a one call deal. Meaning, you are done. call Reporting101a.describeTables_v2a('stackoverflow',@theOutVar,false,true); -- See **Note4** -- Primarily used if the 4th parameter above is false call Reporting101a.Print_Tables_Like_Describe(@theOutVar); -- loads data for prettier results in chunk format. 

Produzione

 +--------------------------------------------------------------------------------------------+ | | +--------------------------------------------------------------------------------------------+ | course | | +------------+--------------+------+-----+---------+----------------+ | | | Field | Type | Null | Key | Default | Extra | | | +------------+--------------+------+-----+---------+----------------+ | | | courseId | int(11) | NO | PRI | | auto_increment | | | +------------+--------------+------+-----+---------+----------------+ | | | deptId | int(11) | NO | MUL | | | | | +------------+--------------+------+-----+---------+----------------+ | | | courseName | varchar(100) | NO | | | | | | +------------+--------------+------+-----+---------+----------------+ | | | | dept | | +----------+--------------+------+-----+---------+----------------+ | | | Field | Type | Null | Key | Default | Extra | | | +----------+--------------+------+-----+---------+----------------+ | | | deptId | int(11) | NO | PRI | | auto_increment | | | +----------+--------------+------+-----+---------+----------------+ | | | deptName | varchar(100) | NO | | | | | | +----------+--------------+------+-----+---------+----------------+ | | | | scjunction | | +------------+---------+------+-----+---------+----------------+ | | | Field | Type | Null | Key | Default | Extra | | | +------------+---------+------+-----+---------+----------------+ | | | id | int(11) | NO | PRI | | auto_increment | | | +------------+---------+------+-----+---------+----------------+ | | | studentId | int(11) | NO | MUL | | | | | +------------+---------+------+-----+---------+----------------+ | | | courseId | int(11) | NO | MUL | | | | | +------------+---------+------+-----+---------+----------------+ | | | term | int(11) | NO | | | | | | +------------+---------+------+-----+---------+----------------+ | | | attendance | int(11) | NO | | | | | | +------------+---------+------+-----+---------+----------------+ | | | grade | int(11) | NO | | | | | | +------------+---------+------+-----+---------+----------------+ | | | | student | | +-----------+--------------+------+-----+---------+----------------+ | | | Field | Type | Null | Key | Default | Extra | | | +-----------+--------------+------+-----+---------+----------------+ | | | studentId | int(11) | NO | PRI | | auto_increment | | | +-----------+--------------+------+-----+---------+----------------+ | | | fullName | varchar(100) | NO | | | | | | +-----------+--------------+------+-----+---------+----------------+ | | | | testtable | | +-----------------------------------------+---------------+------+-----+---------+-------+ | | | Field | Type | Null | Key | Default | Extra | | | +-----------------------------------------+---------------+------+-----+---------+-------+ | | | noPKhere | int(11) | NO | | | | | | +-----------------------------------------+---------------+------+-----+---------+-------+ | | | veryLongColumnName_And_Then.Some_%_More | decimal(12,2) | YES | | | | | | +-----------------------------------------+---------------+------+-----+---------+-------+ | | | limit | int(11) | NO | | | | | | +-----------------------------------------+---------------+------+-----+---------+-------+ | | | | testtable2 | | +-------+---------+------+-----+---------+-------+ | | | Field | Type | Null | Key | Default | Extra | | | +-------+---------+------+-----+---------+-------+ | | | id | int(11) | NO | PRI | | | | | +-------+---------+------+-----+---------+-------+ | +--------------------------------------------------------------------------------------------+ 

Nota 1 : un database denominato Reporting101a viene creato per ospitare due stored procedure e alcune tabelle di supporto. Queste routine iniziano con una chiamata una procedura memorizzata che fa riferimento al database da segnalare tramite l’uso di una stringa.

I dati per produrre l’output sono accessibili attraverso lo speciale database INFORMATION_SCHEMA in un modo sicuro di sola lettura. In questo modo, il database segnalato non viene toccato.

Ci sono tre tabelle non temporanee conservate in questo database.

  1. reportDataDefsSession – Una semplice tabella utilizzata per ottenere una sessione #
  2. reportDataDefs – data returne from INFORMATION_SCHEMA e massaggiato un po ‘. È basato sulla sessione.
  3. reportOutput – Una tabella per la stampa come DESCRIBE di MySQL. È solo una tabella per mettere insieme l’output. È basato sulla sessione.

Nota2 : questa variabile INT è inclusa come destinazione del parametro OUT , scritta su, e consente di incunearsi all’altro codice dopo che la prima stored procedure ha preparato i dati. Rappresenta una sessione # che isola l’output per rapporti successivi.

Alcuni ambienti come PHP hanno alcuni trucchi che lo rendono uno spettacolo per alcuni programmatori. Quindi, se hai bisogno di combinare entrambe le stored procedure da solo, fallo (o chiedimi di farlo separatamente se sei confuso).

In ogni caso, mostra come i dati o gli sforzi possono raggruppare le chiamate di procedura memorizzate.

Onestamente, uno dei motivi principali per cui sono uscito con una sessione # come parametro OUT è che so che devo creare un CURSOR per ottenere il risultato migliore. E ciò richiede un Cursor DECLARE nella parte superiore di una seconda procedura memorizzata. E DECLARE s deve verificarsi nella parte superiore di una stored procedure. Così con le mani legate, sono andato su questa strada.

Nota3 : questa è la chiamata alla prima stored procedure. È molto probabile che tu abbia finito dopo che questa chiamata ha TRUE come quarto parametro. La stored procedure è piuttosto ben documentata al suo interno. Il terzo parametro indica se vuoi o meno cancellare i dati dalla tabella di rapporto per la sessione #. L’eliminazione si verifica dopo ogni output come set di risultati. Quindi, questo dipende dalla tua scelta.

parametri:

  1. il nome del database per descrivere tutte le tabelle come describe myTable
  2. il parametro INT OUT per contenere la sessione #
  3. booleano: vuoi che i dati cancellati dalla tabella di rapporto alla fine
  4. booleano: dovremmo chiamare automaticamente la bella procedura memorizzata di stampa che genera un output describe . Se si decide di passare il parametro 4 come FALSE , l’output potrebbe essere simile a questo:

inserisci la descrizione dell'immagine qui

Nota4 : utilizzata nei casi in cui si desidera un output diverso ma si desidera utilizzare la sessione #. In genere non ne hai bisogno.

Devi solo cancellare la prima e l’ultima riga dell’output della tabella e sostituire + da | avere un formato di markdown per la tabella.

come questo:

 |Field|Type|Null|Key|Default|Extra| |-----|----|----|---|-------|-----| |blockheight|int(11)|No|PRI|NULL|| ...