准备好的选择语句的结果作为数组

Posted

技术标签:

【中文标题】准备好的选择语句的结果作为数组【英文标题】:result of prepared select statement as array 【发布时间】:2018-12-21 19:33:47 【问题描述】:

我想以数组(键/值对)的形式获取准备好的语句的完整结果,以便稍后在 str_replace() 函数中使用它。

我的表有三列,一个索引和字段“x1”和“x2”。我成功使用了以下内容:

$db = new mysqli("servername", "username", "pw", "dbname");

if($ps1 = $db->prepare("SELECT x1, x2 FROM my_table")) 
  $ps1->execute();
  $ps1->bind_result($search, $replace);
    $result = array();
    while ($ps1->fetch()) 
      $result[$search] = $replace;
    
    $ps1->close();

但是,我认为必须有一种更简单的方法,没有while 循环,得到完整的结果,而不是从单行一一相加。

我查看了其他问题,想出了以下问题,但它不起作用(“警告:mysqli_fetch_assoc() 期望参数 1 为 mysqli_result”):

if($ps1 = $db->prepare("SELECT x1, x2 FROM my_table")) 
  $ps1->execute();
  $result = mysqli_fetch_assoc($ps1);
  return $result;
  $ps1->close();

我也尝试了$result = mysqli_fetch_all($ps1);,但没有成功(得到“调用未定义函数 mysqli_fetch_all()”)。

顺便说一句,我使用的是 php 5.6。


在 cmets 中有关 MYSQLND 的一些答案和讨论后添加:

phpinfo() 在其mysqlnd 部分显示以下信息:

加载的插件: mysqlnd,debug_trace,auth_plugin_mysql_native_password,auth_plugin_mysql_clear_password,auth_plugin_sha256_password

【问题讨论】:

不确定为什么会出现该错误。不过,您应该全程使用 OOP。不过,该函数 php.net/manual/en/mysqli-result.fetch-assoc.php 仍然只返回 1 行。可以试试php.net/manual/en/mysqli-result.fetch-all.php。 php.net/manual/en/mysqli.error.php 是否提供更多关于为什么 $ps1 不是结果对象的信息? @user3783243 感谢您的回答!我尝试了$result = mysqli_fetch_all($ps1);,但没有成功(“调用未定义的函数 mysqli_fetch_all()”)。抱歉,这个我慢。你能推荐一段代码吗? 您使用的是什么 PHP 版本?此外,我认为您仍然会遇到$ps1 的问题,因为基于该错误它不是结果对象,请尝试printf("Errormessage: %s\n", $ps1->error); 我更多的是 PDO 用户,这正在离开我的专业领域,但查看其他论坛/线程,似乎需要配置 mysqlnd 【参考方案1】:

确实有更简单的方法。请考虑使用array_column:

$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) 
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();


$query = "SELECT x1, x2 FROM my_table";

if ($stmt = mysqli_prepare($link, $query)) 

    /* execute statement */
    mysqli_stmt_execute($stmt);

    /* get result object */
    $rows = mysqli_fetch_all(mysqli_stmt_get_result($stmt), MYSQLI_ASSOC);

    /* get formatted object */
    $result = array_column($rows, 'x2', 'x1');

    /* close statement */
    mysqli_stmt_close($stmt);


/* close connection */
mysqli_close($link);

编辑:更新了使用程序 mysqli 函数的答案

【讨论】:

与其他答案相同:您的代码使用 PDO(我没有),所以我得到 Call to undefined method mysqli_stmt::fetchAll() in ... 我已经更新了我的答案,并对其进行了测试。它做你想做的事 与其他答案相同的问题:Fatal error: Call to undefined function mysqli_fetch_all() 好的,你能发布 phpinfo() 的结果吗?所以我们知道我们在处理什么 请注意我的问题的补充【参考方案2】:

你尝试过这样的事情吗?

$db = new mysqli("servername", "username", "pw", "dbname");

if($ps1 = $db->prepare("SELECT x1, x2 FROM my_table")) 
  $ps1->execute();
  $result = $ps1->fetchAll(PDO::FETCH_NAMED);
  $ps1->close();

更新

我的意思是这样(如果你已经安装了mysqlnd驱动)

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) 
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();


$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 150,5";

if ($stmt = mysqli_prepare($link, $query)) 

    /* execute statement */
    mysqli_stmt_execute($stmt);

    /* get result object */
    $result = mysqli_fetch_all(mysqli_stmt_get_result($stmt));

    /* close statement */
    mysqli_stmt_close($stmt);


/* close connection */
mysqli_close($link);
?>

【讨论】:

好吧:您的代码使用 PDO(我没有),所以我得到 Call to undefined method mysqli_stmt::fetchAll() in ... 如果你不使用 PDO - 那么你必须自己迭代结果集 - 完全如官方手册中所示php.net/manual/en/mysqli-stmt.fetch.php 你的意思是像我在问题的第一部分中发布的代码一样?... 回复:您的编辑:这适用于打印结果,但这就像我的问题中的第一个代码示例(我必须使用 while 循环来填充新数组):它没有t 给我一个包含所有键/值对的数组,我以后可以在后续函数中使用它。 复杂性通常是主观的 :)) 即使底层连接器库提供了一次获取所有结果的方法 - 它不一定适用于高级语言。迭代结果集是一种标准做法——就像我们迭代 html 表格行和单元格一样。【参考方案3】:

这就是我 fetch_all 使用 mysqli 准备语句的结果

$stmt = $db->prepare("SELECT x1, x2 FROM my_table")
$stmt->execute();
$result = $stmt->get_result();
$allRows = $result->fetch_all(MYSQLI_ASSOC);

【讨论】:

这给了我Fatal error: Call to undefined method mysqli_stmt::get_result()... @Johannes 你可能没有安装mysqlnd driver。检查这个answer 不幸的是,我无权在该服务器(共享网络空间)上安装任何东西,我必须使用给定的配置和它提供的几个选项...... 在这种情况下,如果您唯一关心的是“更简单的代码”,为什么不在函数中包含该获取循环并在您的主代码中调用它。可能还有其他解决方案,但很抱歉我只知道这些【参考方案4】:

请原谅我的英语

我认为这是不可能的,因为mysqli_fetch_assoc()mysqli_result 作为参数,而mysqli-&gt;prepare-&gt;execute 返回mysqli_stmt 对象。

您可以做的是使用JesusTheHun's 答案的程序方式,或者您可以使用$ps1 = $db-&gt;query($stmt) 而不是prepare and execute,然后将其传递给$ps1-&gt;fetch_all(MYSQLI_ASSOC)

例子:

if($ps1 = $db->query("SELECT x1, x2 FROM my_table")) 
  $result = $ps1->fetch_all(MYSQLI_ASSOC);

  $ps1->close();
  return $result;


print_r($result);

mysqli 的 PHP 文档

【讨论】:

在return语句后关闭$ps1有什么意义?【参考方案5】:

您可以尝试使用如下函数扩展 mysqli_result 类:

public function my_fetch_keyval() 
    for ($result = array(); $tmp = $this->fetch_row();) 
        // Expecting 2 columns. 1st = Key; 2nd = Value
        $result[$tmp[0]] = $tmp[1];
    
    return $result;

然后你可以在你的代码中使用它:

if($ps1 = $db->prepare("SELECT x1, x2 FROM my_table")) 
    $ps1->execute();
    $my_assoc_array = $ps1->my_fetch_keyval();
    $ps1->close();

【讨论】:

【参考方案6】:

编辑:我浏览了您的 cmets 和其他答案,很明显您没有 Mysql 本机驱动程序。

如果你不想使用mysqlnd,我相信你不能摆脱那个while循环;)

================================================ ==============

你好像错过了一件事!

您需要调用get_result() 方法,然后对该对象调用fetch_all()

$db = new mysqli("servername", "username", "pw", "dbname");

if($ps1 = $db->prepare("SELECT x1, x2 FROM my_table")) 
    $ps1->execute();
    $result = $ps1->get_result()->fetch_all();
    //return $result;
    $ps1->close();


echo '<pre>';
print_r($result);

另外请注意,我已经注释掉了 return 语句,因为它会在此时终止脚本的执行。

希望对你有帮助:)

【讨论】:

【参考方案7】:

根据之前的答案(没有正确的mysqlnd 分机 - 有两个,一个用于mysqli,一个用于PDO),我们可以得出结论,您有两个选择,您可以使用带有 while 循环或标准查询的准备好的语句,但会将结果作为关联数组返回。

由于你没有任何参数,你可以安全地使用普通的 ole 查询,因为:

a) 没有您必须转义的用户输入,您的语句中没有参数,因此没有安全风险

b) 准备好的语句的性能提升是疏忽的,因为您将它用作普通的 ole SQL 查询。当您一遍又一遍地重复使用相同的语句时,只更改绑定到它的参数值,准备好的语句就会大放异彩

让我们切入正题:

$conn = mysqli($host, $user, $pass, $dbname);

$query = $conn->query("SELECT x1, x2 FROM your_table");

$result = $query->fetch_assoc();

结果将采用以下格式:

[
   'x1' => 'v1',
   'x2' => 'v2'
]

如果您需要整个数据集而不仅仅是一个项目,请使用以下内容:

$result = $query->fetch_all(MYSQLI_ASSOC);

结果将如下所示:

[
    [
      'x1' => 'v1',
      'x2' => 'v2'
   ],
   [
     'x1' => 'v1',
     'x2' => 'v2'
   ],
   ...
]

更新

现在我看到mysqli::fetch_all 也会为您抛出一个错误,那么恐怕没有循环就无法获取整个数据集。如果您想要替代您的方法,可能是这样的:

$query = $conn->query("SELECT x1, x2 FROM your_table");

$results = [];
for ($i = 0; $i < $query->num_rows; $i++) 
    $row = $query->fetch_assoc();
    $results[$row['x1']] = $row['x2'];

或者这个:

while($row = $query->fetch_assoc()) 
   $results[$row['x1']] = $row['x2'];  

但老实说,那你不妨按照你最初的方式去,如果你没有mysqli::fetch_all 可用,这是最好的方法

【讨论】:

以上是关于准备好的选择语句的结果作为数组的主要内容,如果未能解决你的问题,请参考以下文章

使用准备好的语句Java选择[重复]

如何使用准备好的语句选择 IP 地址

如何在 Java 中使用准备好的语句进行选择查询?

从准备好的语句中获取数据

什么时候在 PHP Mysqli 中使用准备好的语句? - 用户表单搜索输入与选择查询

如果我使用一个语句选择属性然后使用多个 sql 查询的 1 个准备好的语句,我是不是需要使用连接池