我想通过AJAX(到PHP后端)向我的数据库发出查询。我有4个表:公司,用户,发票,Invoice_Lines。重要的关系如下:
Users.Company_ID -> Companies.ID
Invoices.Company_ID -> Companies.ID
Invoice_Lines.Invoice_ID -> Invoices.ID
我在PHP中编写了一个简单的解析器,它将提交的SQL查询分解为其组件(列,表和条件)。
我希望用户能够直接编写查询,但在将它们提交到SQL服务器之前对其进行修改,以便所有信息都受登录用户的公司ID限制。例如:
SELECT Users.ID, Users.Name, Users.Email
FROM Users
我希望查询成为:
SELECT Users.ID, Users.Name, Users.Email
FROM Users
WHERE Users.Company_ID = X
在一个更复杂的例子中:
SELECT Invoice_Lines.Subtotal
FROM Invoice_Lines
WHERE Invoice_Lines.Invoice_ID = 4
变为
SELECT Invoice_Lines.Subtotal
FROM Invoice_Lines
INNER JOIN Invoices ON (Invoice_Lines.Invoice_ID = Invoice.ID)
INNER JOIN Company ON (Invoice.Company_ID = Company.ID)
WHERE Invoice_Lines.Invoice_ID = 4 AND Company.ID = X
很明显,我必须创建不会与已经编写的语句冲突的表别名。我不确定如何分析查询以确定限制输入的最有效方法。
我打算只支持SQL的一个子集(带有别名的直接表列,带表和别名的左连接和内连接以及表达式的简单表达式)。
答案 0 :(得分:0)
同样,我建议查看Zend Framework如何用Zend_Db_Select以OP方式描述SQL语句。
1)定义基本SQL语句,其中包括要从中选择列的所有表。
让我们说:
SELECT *
FROM table1
LEFT JOIN table2 on table2.table1Id = table1.id
LEFT JOIN table3 on table3.table2Id = table2.id
LEFT JOIN table4 on table4.table3Id = table3.id
2)你将允许用户选择列(最终我也想象约束) - 使用当然可以换出对象的数组。
$fields = array(
'table1' => array(array('col1'/*actual field name*/ => 'col1_Alias' /*assigned alais*/), array('col2'=>'col2_Alias')
'table2' => array(array('col1'=>'col1_Alias'), array('col2'=>'col2_Alias')
etc...
);
在控制器上定义它,将其用于构建查询时为用户提供的选项。然后在提交选择时使用它来构建SQL ...
伪代码......
foreach ($selectColumns as $table => $col) {
$cols[] = "{$table}.{$col['field']} AS {$col['alias']}";
}
在该循环中,您可以跟踪引用的每个表,并可能确定您将要执行的SQL语句中是否需要它。需要描述JOINS的性质才能正确地做到这一点 - 再次输入像Zend_Db_Select这样的OOP能力。
在我的回答中没有多少肉,但希望它有所帮助。