设置 MySQL 查询结果的格式,就像从控制台运行一样

发布于 2024-10-10 11:24:02 字数 482 浏览 6 评论 0原文

我正在编写一个快速而肮脏的报告脚本,用于查询报告并通过电子邮件发送结果。当使用 MySQL 控制台时,结果位于一个格式良好的表中:

mysql> select * from users;
+-----------+------------+-------+
| firstname | city       | zip   |
+-----------+------------+-------+
| Maria     | Holland    | 12345 |
| Rene      | Doylestown | 65432 |
| Helen     | Conway     | 98745 |
+-----------+------------+-------+
3 rows in set (0.01 sec)

当使用 PHP 获取结果时,是否有一种简单的方法来复制这种格式?显然,我可以通过编写自己的报告格式化程序来实现这一目标,但我希望有一些更优雅的东西。

I'm writing a quick and dirty reporting script that queries a report and emails the results. When using the MySQL console the results are in a nicely formatted table:

mysql> select * from users;
+-----------+------------+-------+
| firstname | city       | zip   |
+-----------+------------+-------+
| Maria     | Holland    | 12345 |
| Rene      | Doylestown | 65432 |
| Helen     | Conway     | 98745 |
+-----------+------------+-------+
3 rows in set (0.01 sec)

Is there an easy way to replicate this formatting when fetching the results with PHP? Obviously I could achieve this by writing my own report formatter but I was hoping for something a little more elegant.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

花开柳相依 2024-10-17 11:24:23

听起来您只需要使用任何一种 exec 方法或反引号即可。我不确定 '\G' 的事情...但是,几个月前我发布了一个名为 query2Table() 的 php 函数 @ http://www.logicwizards.net/php-query2table——基于我多年来一直重复使用的函数。我有一堆多年来积累的:query2xml、query2excel、query2json 等。我想我仍然有旧的 perl & 。某处也有 asp 版本。

基本上,在我的解决方案中,您只需向其传递查询字符串,它就会使用从结果中获取的列名称作为表的标题行动态地吐出一个 html 表。它还会增长以填充其继承的容器对象的宽度。

  query2table("select * from table;");

我有一个更新版本的 query2AjaxTable() ,它将所有内容很好地包装在一个类中,并添加了 jQuery 排序和排序。动画——但尚未准备好发布。

如果我的愚蠢的小功能不能帮助你,在你的困境中,也许其他人会发现它有用......

it sounds like you just need to use any one of the exec methods or backticks. I'm not sure about the '\G' thingy... but, I published a php function called query2Table() a few months ago @ http://www.logicwizards.net/php-query2table -- based on a function I've been recycling for years. I have a bunch that I've accumulated over the years: query2xml, query2excel, query2json, etc. I think I still have the old perl & asp versions somewhere, too.

Basically, in my solution, you can just pass it the query string and it dynamically spit's out an html table using column names fetched from the results as the table's header row. It also grows to fill the width of it's inherited container object.

  query2table("select * from table;");

I have a more up to date version query2AjaxTable() which wraps everything up nicely in a class and adds jQuery sorting & animations -- but it's not ready for publishing yet.

If my silly little function doesn't help you, in your dilemma, maybe someone else will find it useful...

奈何桥上唱咆哮 2024-10-17 11:24:21

我优化了 @ehudokai 的答案,因此它使用更少的循环(5 vs 9)。为了完整起见,我还添加了命令行、统计信息和错误输出:

<pre>
<?php
$db = mysqli_connect('localhost', 'my_user', 'my_password', 'my_db');
$start = microtime(true);
$sql = "SELECT * FROM myTable";
$result = mysqli_query($db, $sql);
$exec_time = microtime(true) - $start;
// obtain the maximum string length of all column headings and rows
$colwidths = array();
while ($row = mysqli_fetch_assoc($result)) {
    foreach ($row as $key => $value) {
        // heading
        if (!isset($colwidths[ $key ])) {
            $colwidths[ $key ] = strlen($key) + 2;
        }
        // rows
        $colwidths[ $key ] = max($colwidths[ $key ], strlen($value) + 2);
    }
}
echo 'mysql>' . trim($sql) . PHP_EOL;
// SELECT, SHOW, DESCRIBE, EXPLAIN = resource
// INSERT, UPDATE, DELETE, DROP = true
// Error = false
if (!is_bool($result)) {
    if ($colwidths) {
        mysqli_data_seek($result, 0);
        while ($row = mysqli_fetch_assoc($result)) {
            // create and display horizontal line and column headings
            if (!isset($header)) {
                $header = '| ';
                $line = '+';
                foreach ($row as $key => $value) {
                    $line .= str_repeat('-', $colwidths[ $key ] + 2) . '+';
                    $header .= str_pad($key, $colwidths[ $key ]) . ' | ';
                }
                echo $line . PHP_EOL;
                echo $header . PHP_EOL;
                echo $line . PHP_EOL;
            }
            // display row values
            foreach ($row as $key => $value) {
                echo '| ' . str_pad($value, $colwidths[ $key ] + 1);
            }
            echo '|' . PHP_EOL;
        }
        echo $line . PHP_EOL;
    }
    mysqli_free_result($result);
}
$affectedrows = mysqli_affected_rows($db);
if ($result === false) {
    echo PHP_EOL . 'ERROR ' . mysqli_errno($db) . ': ' . mysqli_error($db);
}
else if ($result === true) {
    echo 'Query OK, ' . $affectedrows . ' rows affected (' . round($exec_time / $iterations * 1000) . ' ms)';
}
else if ($affectedrows) {
    echo $affectedrows . ' rows in set (' . round($exec_time / $iterations * 1000) . ' ms)';
}
else {
    echo 'Empty set (' . round($exec_time / $iterations * 1000) . ' ms)';
}
?>
</pre>

示例

SELECT

mysql>SELECT
        topic_id,
        MATCH(text) AGAINST('tuning') AS score
    FROM
        topics
    WHERE
        MATCH(text) AGAINST('tuning' IN BOOLEAN MODE)
    ORDER BY
        score DESC
    LIMIT 10
+----------+--------------------+
| topic_id | score              |
+----------+--------------------+
| 153257   | 5.161948204040527  |
| 17925    | 4.781417369842529  |
| 66459    | 4.648380279541016  |
| 373176   | 4.570812702178955  |
| 117173   | 4.55166482925415   |
| 167016   | 4.462575912475586  |
| 183286   | 4.4519267082214355 |
| 366132   | 4.348565101623535  |
| 95502    | 4.293642520904541  |
| 29615    | 4.178250789642334  |
+----------+--------------------+
10 rows in set (141 ms)

Error:

mysql>SELECT * WHERE 1=1

ERROR 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE 1=1' at line 1

UPDATE

mysql>UPDATE topics_search SET topic_id = topic_id WHERE topic_id = 2
Query OK, 0 rows affected (0 ms)

I optimized the answer of @ehudokai so it uses less loops (5 vs 9). And for completeness I added the command line, stats and error output, too:

<pre>
<?php
$db = mysqli_connect('localhost', 'my_user', 'my_password', 'my_db');
$start = microtime(true);
$sql = "SELECT * FROM myTable";
$result = mysqli_query($db, $sql);
$exec_time = microtime(true) - $start;
// obtain the maximum string length of all column headings and rows
$colwidths = array();
while ($row = mysqli_fetch_assoc($result)) {
    foreach ($row as $key => $value) {
        // heading
        if (!isset($colwidths[ $key ])) {
            $colwidths[ $key ] = strlen($key) + 2;
        }
        // rows
        $colwidths[ $key ] = max($colwidths[ $key ], strlen($value) + 2);
    }
}
echo 'mysql>' . trim($sql) . PHP_EOL;
// SELECT, SHOW, DESCRIBE, EXPLAIN = resource
// INSERT, UPDATE, DELETE, DROP = true
// Error = false
if (!is_bool($result)) {
    if ($colwidths) {
        mysqli_data_seek($result, 0);
        while ($row = mysqli_fetch_assoc($result)) {
            // create and display horizontal line and column headings
            if (!isset($header)) {
                $header = '| ';
                $line = '+';
                foreach ($row as $key => $value) {
                    $line .= str_repeat('-', $colwidths[ $key ] + 2) . '+';
                    $header .= str_pad($key, $colwidths[ $key ]) . ' | ';
                }
                echo $line . PHP_EOL;
                echo $header . PHP_EOL;
                echo $line . PHP_EOL;
            }
            // display row values
            foreach ($row as $key => $value) {
                echo '| ' . str_pad($value, $colwidths[ $key ] + 1);
            }
            echo '|' . PHP_EOL;
        }
        echo $line . PHP_EOL;
    }
    mysqli_free_result($result);
}
$affectedrows = mysqli_affected_rows($db);
if ($result === false) {
    echo PHP_EOL . 'ERROR ' . mysqli_errno($db) . ': ' . mysqli_error($db);
}
else if ($result === true) {
    echo 'Query OK, ' . $affectedrows . ' rows affected (' . round($exec_time / $iterations * 1000) . ' ms)';
}
else if ($affectedrows) {
    echo $affectedrows . ' rows in set (' . round($exec_time / $iterations * 1000) . ' ms)';
}
else {
    echo 'Empty set (' . round($exec_time / $iterations * 1000) . ' ms)';
}
?>
</pre>

Examples

SELECT

mysql>SELECT
        topic_id,
        MATCH(text) AGAINST('tuning') AS score
    FROM
        topics
    WHERE
        MATCH(text) AGAINST('tuning' IN BOOLEAN MODE)
    ORDER BY
        score DESC
    LIMIT 10
+----------+--------------------+
| topic_id | score              |
+----------+--------------------+
| 153257   | 5.161948204040527  |
| 17925    | 4.781417369842529  |
| 66459    | 4.648380279541016  |
| 373176   | 4.570812702178955  |
| 117173   | 4.55166482925415   |
| 167016   | 4.462575912475586  |
| 183286   | 4.4519267082214355 |
| 366132   | 4.348565101623535  |
| 95502    | 4.293642520904541  |
| 29615    | 4.178250789642334  |
+----------+--------------------+
10 rows in set (141 ms)

Error:

mysql>SELECT * WHERE 1=1

ERROR 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE 1=1' at line 1

UPDATE

mysql>UPDATE topics_search SET topic_id = topic_id WHERE topic_id = 2
Query OK, 0 rows affected (0 ms)
深海里的那抹蓝 2024-10-17 11:24:19

考虑到在 PHP 中从 MySQL 获取数据的方式,这没有任何意义。 (即:您通常一次以数组形式获取一行数据(mysql_fetch_array) 或一个对象 (mysql_fetch_object< /a>).)

因此,您需要编写自己的 hack 来获取所有行并以这种方式格式化输出。 (也就是说,获取数据并将其输出为 HTML 表应该很简单 - 您可以通过 获取字段名称array_keys 如果你使用mysql_fetch_array等)

This doesn't make any sense bearing in mind the manner in which you fetch data from MySQL in PHP. (i.e.: You generally fetch onw row of data at a time either as an array (mysql_fetch_array) or an object (mysql_fetch_object).)

As such, you'd need to write your own hack to grab all of the rows and format the output in this manner. (That said, it should be trivial to grab the data and output it as an HTML table - you could get the field names via array_keys if you use mysql_fetch_array, etc. )

—━☆沉默づ 2024-10-17 11:24:16

基于 mfonda 的答案,您可以轻松加载 Console_Table现在使用作曲家的 pear 包https://packagist.org/packages/pear/console_table< /a>

$composer require pear/console_table

<?php
//Suppress E_DEPRECATED errors for statically calling a non-static method (this package is pretty old!)
error_reporting(E_ALL & ~E_DEPRECATED);
require __DIR__ . '/vendor/autoload.php';

//echo "<pre>"; #uncomment this line if running script in a browser

//The class isn't namespaced so just call it directly like so:
echo Console_Table::fromArray(
    ['column', 'headings'], 
    [
        ['1st row', 'values'], 
        ['2nd row', 'values'], 
        ['...', '...']
    ]
);

这输出:

+---------+----------+
| column  | headings |
+---------+----------+
| 1st row | values   |
| 2nd row | values   |
| ...     | ...      |
+---------+----------+

Building on mfonda's answer, you can really easily load the Console_Table pear package with composer now: https://packagist.org/packages/pear/console_table

$ composer require pear/console_table

<?php
//Suppress E_DEPRECATED errors for statically calling a non-static method (this package is pretty old!)
error_reporting(E_ALL & ~E_DEPRECATED);
require __DIR__ . '/vendor/autoload.php';

//echo "<pre>"; #uncomment this line if running script in a browser

//The class isn't namespaced so just call it directly like so:
echo Console_Table::fromArray(
    ['column', 'headings'], 
    [
        ['1st row', 'values'], 
        ['2nd row', 'values'], 
        ['...', '...']
    ]
);

This outputs:

+---------+----------+
| column  | headings |
+---------+----------+
| 1st row | values   |
| 2nd row | values   |
| ...     | ...      |
+---------+----------+
猫卆 2024-10-17 11:24:14

您可以使用 exec 或反引号并通过 php 从命令行实际运行它。显然 mysql 命令有一个可以使用的 -H 开关,它将输出 HTML 格式。虽然还没有尝试过,但这看起来也不错。

echo '<pre>';
echo `mysql -u user -ppass -e "select * from table;" database_name`;

2行,没有pear包,对于一个快速而肮脏的统计页面来说,它能变得多么优雅啊。

You could use exec or backticks and actually run it from the command line through php. Apparently the mysql command has a -H switch you can use, and it will output HTML formatted. Haven't tried it though, but that might look good too.

echo '<pre>';
echo `mysql -u user -ppass -e "select * from table;" database_name`;

2 lines, no pear packages, how much more elegant can it get for a quick and dirty stats page.

探春 2024-10-17 11:24:12

你必须自己做。

执行一个循环来查找每列的最大大小。然后将每行填充输出为该大小+2,并在开头和结尾处留有空格。用 | 分隔每列。

使用 + 和 - 创建顶部和底部。

如果不知道您使用什么来获得结果,则很难给出具体的示例。但假设您正在使用 mysql_query。这是一个例子。

$conn = mysql_connect("localhost", "mysql_user", "mysql_password");
mysql_select_db("mydbname");
$result = mysql_query("SELECT * FROM myTable");
//first get your sizes
$sizes = array();
$row = mysql_fetch_assoc($result);
foreach($row as $key=>$value){
    $sizes[$key] = strlen($key); //initialize to the size of the column name
}
while($row = mysql_fetch_assoc($result)){
    foreach($row as $key=>$value){
        $length = strlen($value);
        if($length > $sizes[$key]) $sizes[$key] = $length; // get largest result size
    }
}
mysql_data_seek($result, 0); //set your pointer back to the beginning.

//top of output
foreach($sizes as $length){
    echo "+".str_pad("",$length+2,"-");
}
echo "+\n";

// column names
$row = mysql_fetch_assoc($result);
foreach($row as $key=>$value){
    echo "| ";
    echo str_pad($key,$sizes[$key]+1);
}
echo "|\n";

//line under column names
foreach($sizes as $length){
    echo "+".str_pad("",$length+2,"-");
}
echo "+\n";

//output data
do {
    foreach($row as $key=>$value){
        echo "| ";
        echo str_pad($value,$sizes[$key]+1);
    }
    echo "|\n";
} while($row = mysql_fetch_assoc($result));

//bottom of output
foreach($sizes as $length){
    echo "+".str_pad("",$length+2,"-");
}
echo "+\n";

这样就可以了(我希望我没有错过其中的分号:))。

希望有帮助!

You have to do it yourself.

do a loop to find the max size for each column. Then output each row padding to that size +2 with a space at the beginning and end. seperate each column with a |.

Use + and - to create your top and bottom.

It's hard to give a concrete example without knowing what you're using to get your results. But assuming you're using mysql_query. Here's an example.

$conn = mysql_connect("localhost", "mysql_user", "mysql_password");
mysql_select_db("mydbname");
$result = mysql_query("SELECT * FROM myTable");
//first get your sizes
$sizes = array();
$row = mysql_fetch_assoc($result);
foreach($row as $key=>$value){
    $sizes[$key] = strlen($key); //initialize to the size of the column name
}
while($row = mysql_fetch_assoc($result)){
    foreach($row as $key=>$value){
        $length = strlen($value);
        if($length > $sizes[$key]) $sizes[$key] = $length; // get largest result size
    }
}
mysql_data_seek($result, 0); //set your pointer back to the beginning.

//top of output
foreach($sizes as $length){
    echo "+".str_pad("",$length+2,"-");
}
echo "+\n";

// column names
$row = mysql_fetch_assoc($result);
foreach($row as $key=>$value){
    echo "| ";
    echo str_pad($key,$sizes[$key]+1);
}
echo "|\n";

//line under column names
foreach($sizes as $length){
    echo "+".str_pad("",$length+2,"-");
}
echo "+\n";

//output data
do {
    foreach($row as $key=>$value){
        echo "| ";
        echo str_pad($value,$sizes[$key]+1);
    }
    echo "|\n";
} while($row = mysql_fetch_assoc($result));

//bottom of output
foreach($sizes as $length){
    echo "+".str_pad("",$length+2,"-");
}
echo "+\n";

That would do it (I hope I didn't miss a semicolon in there :) ).

Hope that helps!

稀香 2024-10-17 11:24:10

您可以使用 Console_Table PEAR 包轻松完成此操作。只需循环遍历 MySQL 结果,并将行添加到表中即可。您可以使用 Console_Table::setHeaders() 方法为列添加标题,然后使用 Console_Table::addRow() 方法添加每一行,最后 < code>Console_Table::getTable() 来显示它。

PHP 中没有内置任何东西来执行此操作。如果您不想使用/编写代码来绘制控制台表,只需使用 passthru() 通过 PHP 将 -e query 传递到 mysql 即可。这将工作以 ;\G 终止的查询:

passthru("mysql -e '$query;' database_name");

You could do this quite easily using the Console_Table PEAR package. Just loop through your MySQL results, and add rows to your table. You can use the Console_Table::setHeaders() method to add the headers for your columns, then the Console_Table::addRow() method to add each row, and finally Console_Table::getTable() to display it.

There is nothing built into PHP to do this. If you don't want to use/write code to draw console tables, just pass -e query to mysql via PHP using passthru(). This will work queries terminated with both ; and \G:

passthru("mysql -e '$query;' database_name");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文