Using Result Set Metadata to Get Table Structure

9.6.5 Using Result Set Metadata to Get Table Structure

Anot her way t o obt ain t able colum n inform at ion is t o use t he m et adat a generat ed when you issue a SELECT st at em ent . See Recipe 9.3 . Met adat a inform at ion is available for any arbit rary query, and t herefore can be obt ained specifically for t he colum ns of a given t able. For exam ple, t he result set for SELECT FROM tbl_name will cont ain m et adat a for each colum n in tbl_name . However, if youre int erest ed only in t he m et adat a, not in t he dat a cont ained in t he t able, youll nat urally want t o m inim ize t he size of t he result set so as t o generat e as lit t le net work t raffic as possible. I t s easy t o guarant ee t hat t he result will be em pt y by adding a WHERE clause t hat is always false: SELECT FROM tbl_name WHERE 1 = 0 Alt hough t his query select s no rows, it s perfect ly legal and MySQL goes ahead and generat es t he m et adat a, from which you can ext ract what ever inform at ion you want . For exam ple, earlier in t his sect ion we wrot e a PHP funct ion get_column_names_with_show t hat get s a list of t he colum n nam es by issuing a SHOW COLUMNS st at em ent . The funct ion can be reim plem ent ed as follows t o get t he colum n nam es from t he query m et adat a inst ead by r unning a SELECT query and calling mysql_fetch_field : function get_column_names_with_meta conn_id, tbl_name { query = SELECT FROM tbl_name WHERE 1 = 0; if result_id = mysql_query query, conn_id return FALSE; names = array ; create empty array for i = 0; i mysql_num_fields result_id; i++ { if field = mysql_fetch_field result_id, i names[ ] = field-name; append name to array } mysql_free_result result_id; return names; } The equivalent funct ion in Perl is sim pler. DBI organizes m et adat a int o arrays, so we j ust need t o access t he sth-{NAME} reference t o t he colum n nam e array. The only t rick is t hat it s necessary t o m ake a copy of t he array before calling finish , because finish dest roys t he m et adat a and renders t he NAME array unavailable: sub get_column_names_with_meta { my dbh, tbl_name = _; my sth, names; sth = dbh-prepare SELECT FROM tbl_name WHERE 1=0; sth-execute ; names = {sth-{NAME}}; make a copy; finish destroys meta info sth-finish ; release result set return names; } You can easily convert t hese funct ions t hat get colum n nam es int o m ore general versions t hat allow you t o specify which kind of m et adat a inform at ion you want . Nam e each funct ion get_column_info and add a param et er for t he inform at ion t ype. I n PHP, t he funct ion looks like t his: function get_column_info conn_id, tbl_name, info_type { query = SELECT FROM tbl_name WHERE 1 = 0; if result_id = mysql_query query, conn_id return FALSE; info = array ; create empty array for i = 0; i mysql_num_fields result_id; i++ { if field = mysql_fetch_field result_id, i info[ ] = field-info_type; append info to array } mysql_free_result result_id; return info; } To use t he funct ion, call it as follows: names = get_column_info conn_id, item, name; types = get_column_info conn_id, item, type; numeric = get_column_info conn_id, item, numeric; The Perl version looks like t his: sub get_column_info { my dbh, tbl_name, info_type = _; my sth, info; sth = dbh-prepare SELECT FROM tbl_name WHERE 1=0; sth-execute ; info = {sth-{info_type}}; make a copy; finish destroys meta info sth-finish ; release result set return info; } And is invoked like t his: my names = get_column_info dbh, item, NAME; my types = get_column_info dbh, item, mysql_type_name; my numeric = get_column_info dbh, item, mysql_is_num; One caut ion t o observe wit h get_column_info is t hat you cant use it t o det erm ine display widt hs for a t ables colum ns. That is, it is not useful for t he mysql_max_length values in Perl or t he max_length values in PHP. When you use colum n m et adat a obt ained from a SELECT st at em ent , t he colum n display widt hs reflect t he widt hs of t he values act ually present in t he result . When t he query is SELECT ... WHERE 1=0 , t he result set is em pt y and t he display widt hs are all zero Portability of SELECT ... WHERE 1=0 The SELECT ... WHERE 1=0 query is reasonably port able across dat abase syst em s, but wont necessarily work wit h all possible engines. I f you want t o use t his query wit h dat abase syst em s ot her t han MySQL t o obt ain t able inform at ion, be sure t o t est it first t o m ake sure it works. Which Method Should You Use to Get Table Information? Can you get away wit h using j ust SHOW COLUMNS or j ust SELECT ... WHERE 1=0 for all your t able inform at ion needs? Not necessarily. The inform at ion t hat t hese approaches provide overlaps, but not com plet ely. I f you want t o det erm ine colum n nam es or w het her or not colum ns can be NULL , you can use eit her m et hod. However, if you want t o know legal m em bers of an ENUM or SET colum n, you m ust use SHOW COLUMNS . Know your t ools, and pick t he right one for t he j ob. The m ost appropriat e m et hod m ay depend on what you want t o know.

9.6.6 Using CREATE TABLE to Get Table Structure