在 PHP 中使用 SQL “WITH”子句
Posted
技术标签:
【中文标题】在 PHP 中使用 SQL “WITH”子句【英文标题】:Using SQL "WITH" Clause in PHP 【发布时间】:2019-08-28 13:57:35 【问题描述】:好的,我的环境是 XAMPP 7.3.8,我使用 php 和 MSSQL 数据库。我已经编写了一些代码来查询数据库,并且工作非常好我遇到的这个问题是,当我想将查询包装在“WITH”子句中时,它会停止工作。我无法理解为什么!
我尝试过所有类型的反引号、单引号和双引号。我只是不知道我在哪里搞砸了!
工作代码:
$sql = "SELECT CASE WHEN CHARINDEX('%',\"Name\")>0 THEN SUBSTRING(\"Name\",1,CHARINDEX('_',\"Name\")-1) ELSE \"Name\" END as \"Full Package Name\",
CASE WHEN CHARINDEX('_',\"Name\")> 0 THEN (select left(\"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\" )+1)+1)+1)+1)-1)) ELSE \"Name\" END as \"Package Name\",
CASE WHEN CHARINDEX('_',\"Name\")> 0 THEN SUBSTRING(\"Name\", CHARINDEX('_',\"Name\",CHARINDEX('_',\"Name\", (CHARINDEX('_',\"Name\",(CHARINDEX('_',\"Name\",(CHARINDEX('_',\"Name\")+1))+1))+1))+1)+1,20) ELSE \"Name\" END as 'Version'
FROM vItem WHERE \"Name\" LIKE 'pkg%'
AND \"Name\" NOT LIKE 'XPF %'
AND \"Name\" NOT LIKE 'pkgc%'
AND \"Name\" NOT LIKE 'PKG_ADD_%'
AND \"Name\" NOT LIKE '%_SWV%'
AND \"Name\" NOT LIKE '% - %'
AND \"Name\" NOT LIKE '%_BETA'
AND \"Name\" NOT LIKE '%SV1'
AND \"Name\" NOT LIKE '% Detection%'
AND CreatedDate > '2016-1-01 01:50:58.120'";
不工作的代码:
$sql = "WITH DATASET AS";
$sql .= "(";
$sql .= "SELECT CASE WHEN CHARINDEX('%',\"Name\")>0 THEN SUBSTRING(\"Name\",1,CHARINDEX('_',\"Name\")-1) ELSE \"Name\" END as \"Full Package Name\",
CASE WHEN CHARINDEX('_',\"Name\")> 0 THEN (select left(\"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\" )+1)+1)+1)+1)-1)) ELSE \"Name\" END as \"Package Name\",
CASE WHEN CHARINDEX('_',\"Name\")> 0 THEN SUBSTRING(\"Name\", CHARINDEX('_',\"Name\",CHARINDEX('_',\"Name\", (CHARINDEX('_',\"Name\",(CHARINDEX('_',\"Name\",(CHARINDEX('_',\"Name\")+1))+1))+1))+1)+1,20) ELSE \"Name\" END as 'Version'
FROM vItem WHERE \"Name\" LIKE 'pkg%'
AND \"Name\" NOT LIKE 'XPF %'
AND \"Name\" NOT LIKE 'pkgc%'
AND \"Name\" NOT LIKE 'PKG_ADD_%'
AND \"Name\" NOT LIKE '%_SWV%'
AND \"Name\" NOT LIKE '% - %'
AND \"Name\" NOT LIKE '%_BETA'
AND \"Name\" NOT LIKE '%SV1'
AND \"Name\" NOT LIKE '% Detection%'
AND CreatedDate > '2016-1-01 01:50:58.120'";
$sql .= ")";
$sql .= "SELECT * FROM Dataset WHERE RowNum <= 3";
这是我尝试在 PHP 中运行的 SQL 查询,它在 SQL SMS 中运行良好:
WITH Dataset AS (
select
CASE WHEN CHARINDEX('%',Name)>0
THEN SUBSTRING(Name,1,CHARINDEX('_',Name)-1)
ELSE Name END as 'Full Package Name',
CASE WHEN CHARINDEX('_',Name)> 0
THEN (select left(Name, charindex('_', Name, charindex('_', Name, charindex('_', Name, charindex('_', Name, charindex('_', Name )+1)+1)+1)+1)-1))
ELSE Name END as 'Package Name',
CASE WHEN CHARINDEX('_',Name)> 0
THEN SUBSTRING(name, CHARINDEX('_',Name,CHARINDEX('_',name, (CHARINDEX('_',name,(CHARINDEX('_',name,(CHARINDEX('_',name)+1))+1))+1))+1)+1,20)
ELSE Name END as 'Version',
ROW_NUMBER() OVER (PARTITION BY (select left(Name, charindex('_', Name, charindex('_', Name, charindex('_', Name, charindex('_', Name, charindex('_', Name )+1)+1)+1)+1)-1)) ORDER BY name DESC) AS RowNum
from vItem WHERE Name LIKE 'pkg%'
and Name not like 'XPF %'
and Name not like '%.%'
and Name not like '%_SWV%'
and Name not like '% - %'
and Name not like '%_BETA'
and Name not like '%SV1'
and Name not like '% Detection%'
and Name not like 'PKG_ADD_%'
--and CreatedDate >'2016-1-01 01:50:58.120'
)
SELECT * FROM Dataset WHERE RowNum <= 3
这是完整的 PHP 代码:
elseif(isset($_POST['PKGList']))
$sql = "WITH \"Dataset\" as";
$sql .= "(";
$sql .= "SELECT CASE WHEN CHARINDEX('%',\"Name\")>0 THEN SUBSTRING(\"Name\",1,CHARINDEX('_',\"Name\")-1) ELSE \"Name\" END as \"Full Package Name\",
CASE WHEN CHARINDEX('_',\"Name\")> 0 THEN (select left(\"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\" )+1)+1)+1)+1)-1)) ELSE \"Name\" END as \"Package Name\",
CASE WHEN CHARINDEX('_',\"Name\")> 0 THEN SUBSTRING(\"Name\", CHARINDEX('_',\"Name\",CHARINDEX('_',\"Name\", (CHARINDEX('_',\"Name\",(CHARINDEX('_',\"Name\",(CHARINDEX('_',\"Name\")+1))+1))+1))+1)+1,20) ELSE \"Name\" END as \"Version\",
FROM vItem WHERE \"Name\" LIKE 'pkg%'
AND \"Name\" NOT LIKE 'XPF %'
AND \"Name\" NOT LIKE 'pkgc%'
AND \"Name\" NOT LIKE 'PKG_ADD_%'
AND \"Name\" NOT LIKE '%_SWV%'
AND \"Name\" NOT LIKE '% - %'
AND \"Name\" NOT LIKE '%_BETA'
AND \"Name\" NOT LIKE '%SV1'
AND \"Name\" NOT LIKE '% Detection%'
AND CreatedDate > '2016-1-01 01:50:58.120'";
$sql .= ")";
$sql .= "SELECT * FROM Dataset WHERE RowNum <= 3";
$params = array();
$options = array( "Scrollable" => SQLSRV_CURSOR_KEYSET );
$results = sqlsrv_query( $conn, $sql , $params, $options );
$row_count = sqlsrv_num_rows( $results );
print_r(sqlsrv_errors(), true);
if ($row_count === false)
echo "Error accessing package data.";
else
echo "";
//echo $row_count;
echo "<table class=\"darkTable\">";
echo "<tr>
<th>Full Package Name | $row_count Packages</th>
<th>Package Name</th>
<th>Verison</th>
<th>Build</th>
</tr>";
while($row = sqlsrv_fetch_array( $results)) //Creates a loop to loop through results
echo "<tr><td>" . $row['Full Package Name'] . "</td><td>" . $row['Package Name'] . "</td><td>" . $row['Version'] . "</td><td><input type=\"submit\" name=\"PKGList\" value=\"BUILD\" class=\"btn btn-primary\"></td></tr>"; //$row['index'] the index here is a field name
echo "</table>";
sqlsrv_close($conn);
$_SESSION['message'] = "Query successfully sent: ".$sql;
else
【问题讨论】:
你遇到了什么错误? 请在sqlsrv_query()
调用后执行print_r(sqlsrv_errors(), true);
并发布错误消息。谢谢。
@demo7up 没有完整的 PHP 代码很难,但我猜你的代码有错误(例如,$sql = 'WITH DATASET AS";
应该是 $sql = "WITH DATASET AS";
)。
@demo7up 请检查来自sqlsrv_query
的结果并发布结果($results = sqlsrv_query( $conn, $sql , $params, $options ); if ($results === false) echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true); exit;
)。您的 T-SQL 语句中有错误。再次感谢。
@demo7up 您在Dataset
中没有RowNum
列,所以WHERE RowNum <= 3
很可能是您出错的原因。
【参考方案1】:
一种可能的解释是RowNum
在您的DataSet
CTE 中没有列。只需更正您的 T-SQL 语句并包含 RowNum
列即可。
<?php
$sql = "WITH DATASET AS";
$sql .= "(";
$sql .= "SELECT
-- Include RowNum column here ...
--ROW_NUMBER() OVER (...) As RowNum,
CASE WHEN CHARINDEX('%',\"Name\")>0 THEN SUBSTRING(\"Name\",1,CHARINDEX('_',\"Name\")-1) ELSE \"Name\" END as \"Full Package Name\",
CASE WHEN CHARINDEX('_',\"Name\")> 0 THEN (select left(\"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\", charindex('_', \"Name\" )+1)+1)+1)+1)-1)) ELSE \"Name\" END as \"Package Name\",
CASE WHEN CHARINDEX('_',\"Name\")> 0 THEN SUBSTRING(\"Name\", CHARINDEX('_',\"Name\",CHARINDEX('_',\"Name\", (CHARINDEX('_',\"Name\",(CHARINDEX('_',\"Name\",(CHARINDEX('_',\"Name\")+1))+1))+1))+1)+1,20) ELSE \"Name\" END as 'Version'
FROM vItem WHERE \"Name\" LIKE 'pkg%'
AND \"Name\" NOT LIKE 'XPF %'
AND \"Name\" NOT LIKE 'pkgc%'
AND \"Name\" NOT LIKE 'PKG_ADD_%'
AND \"Name\" NOT LIKE '%_SWV%'
AND \"Name\" NOT LIKE '% - %'
AND \"Name\" NOT LIKE '%_BETA'
AND \"Name\" NOT LIKE '%SV1'
AND \"Name\" NOT LIKE '% Detection%'
AND CreatedDate > '2016-1-01 01:50:58.120'";
$sql .= ")";
$sql .= "SELECT * FROM Dataset WHERE RowNum <= 3";
...
?>
【讨论】:
【参考方案2】:这不是一个确切的答案,但这里的一种解决方法是内联 CTE:
SELECT *
FROM
(
SELECT CASE WHEN CHARINDEX('%', Name) > 0
THEN SUBSTRING(Name, 1, CHARINDEX('_', Name) - 1)
ELSE Name END AS [Full Package Name],
...,
ROW_NUMBER() OVER (PARTITION BY (select left(Name, charindex('_', Name, charindex('_', Name, charindex('_', Name, charindex('_', Name, charindex('_', Name )+1)+1)+1)+1)-1)) ORDER BY name DESC) AS RowNum
FROM vItem
...
) Dataset
WHERE RowNum <= 3;
假设您使用 CTE 所涉及的唯一问题,这应该可行。
【讨论】:
以上是关于在 PHP 中使用 SQL “WITH”子句的主要内容,如果未能解决你的问题,请参考以下文章
如何在标准 SQL 的 WHERE 子句中使用 WITH 子查询作为选项列表
哪个更快? Spark SQL with Where 子句或在 Spark SQL 之后在 Dataframe 中使用过滤器