1

我的数据库中有 2 列包含文本(Products CodeProducts Variant)。

例如:
Products Code保存以下文本:C050101、C070104

Products Variant保存以下文本:RED、NULL

我想选择所有行WHERE Code = Products Code AND Variant = Products Variant
根据我上面写的例子,我应该得到 2 行:
第一行WHERE Code=C050101 and Variant=RED
第二行WHERE Code=C070104 and Variant IS NULL<< IS NULL

我不知道该怎么做...
如果我只需要选择所有行,我就会知道该怎么做WHERE Code = Products Code>>

$arr = array('C050101','C070104');
$inclause = implode(',',array_fill(0,count($arr),'?'));
$stockstmt = $pdo->prepare(sprintf("SELECT `id`, `WebTitle`, `StockCode` FROM `stock` WHERE `StockCode` IN(%s)",$inclause));
$stockstmt->execute($arr);

我将衷心感谢您的帮助。
谢谢!

4

1 回答 1

2

您不能IN为此使用谓词,因为IN只知道如何比较=并且您需要进行不同的比较以处理 NULL。

MySQL 有一个非标准的空安全相等运算符<=>,它知道 NULL=NULL 为真,而 NULL = 'RED' 为假。

如果您使用 MySQL 以外的其他东西,您的 RDBMS 可能支持IS [NOT] DISTINCT类似谓词的标准 SQL 语法。

我测试了以下,它的工作原理:

$arr = array('C050101','RED', 'C070104', NULL);

$sql = "SELECT `id`, `WebTitle`, `StockCode` FROM `stock`
  WHERE (`StockCode`, `StockVariant`) <=> (?, ?)
     OR (`StockCode`, `StockVariant`) <=> (?, ?)";

$stockstmt = $pdo->prepare($sql);
if ($stockstmt === false) { die(print_r($pdo->errorInfo(), true)); }

$status = $stockstmt->execute($arr);
if ($status === false) { die(print_r($stockstmt->errorInfo(), true)); }

我将把它留给您如何构建谓词列表。


回复您的评论:

不建议使用文字字符串“NULL”来表示缺失或不适用的值。这就是 NULL 在 SQL 中的用途。

如果您想要一个使构建谓词更加动态的函数,请尝试以下操作:

function lookformultiplethings(array $arr)
{
  global $pdo;

  $where = array();
  $values = array();
  foreach ((array) $arr as $term) {
    $where[] = '('
        . join(',', array_map(function ($col) {return "`$col`";}, array_keys($term)))
        . ') <=> ('
        . join(',', array_fill(0,count($term),'?'))
        . ')';
    $values = array_merge($values, array_values($term));
  }
  $sql = "SELECT `id`, `WebTitle`, `StockCode` FROM `stock` ";
  if ($where) {
    $sql .= "WHERE " . join(' OR ', $where);
  }

  $stockstmt = $pdo->prepare($sql);
  if ($stockstmt === false) { die(print_r($pdo->errorInfo(), true)); }

  $status = $stockstmt->execute($values);
  if ($status === false) { die(print_r($stockstmt->errorInfo(), true)); }

  print_r($stockstmt->fetchAll());
}

lookformultiplethings(array(
  array('StockCode' => 'C050101', 'StockVariant' => 'RED'),
  array('StockCode' => 'C070104', 'StockVariant' => 'NULL'),
));

请注意,您传递的数组的键是合法的列名。也就是说,除非您根据真实列的白名单对其进行验证,否则不要让用户输入设置列名。

于 2012-11-30T21:20:52.873 回答