CodeIgniter 2.0.3 中 Active Record 中奇怪的反引号行为

发布于 2024-12-05 11:42:59 字数 2466 浏览 1 评论 0原文

以前,我的所有查询在 CI 2.0 版本中运行良好,但当我升级到 2.0.3 时,我的一些 SELECT 查询被破坏了。

CI 会自动添加反引号 (``),但在旧版本中它会按原样运行。

CI 用户手册已指示添加第二个参数

数据库->选择

错误

但仍然不起作用。

代码如下:

class Company_model extends MY_Model
{

----------------

$this->db->select(' count('.$fieldname. ') as num_stations');
$this->db->select(" CONCAT_WS(',', clb_company.address1, clb_company.address2, clb_company.city, clb_company.state, clb_company.zipcode ) as companyAddress");
$this->db->from($this->_table);
$this->db->join($this->_table_device, $fieldname1. " = ".  $fieldname2, 'LEFT');
$this->db->where($blablafield , '0');
----------------

错误如下:

Error Number: 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 
'FROM (`clb_device`) JOIN `clb_company` ON `clb_company`.`id` = `clb_device`.`com' at line 2

SELECT `clb_device`.`id` as deviceId, `clb_pricing_specifications`.`name` as pricingSpecName, `clb_company`.`name` as companyName, `clb_device`.`mac_address` as deviceMacAddress, 
`clb_device`.`reseller_model_number` as deviceModelNumber, `clb_pricing_spec_grouping`.`pricing_master_spec_id` as pricingSpecId, `clb_device`.`address` as deviceAddress, 
`clb_device`.`is_home` as deviceIsHomeCharger, CONCAT(clb_company.portal_line1, `'/'`, `clb_device`.`name)` as deviceDisplayName FROM (`clb_device`) JOIN `clb_company` 
ON `clb_company`.`id` = `clb_device`.`company_id` LEFT JOIN `clb_pricing_group_devices` ON `clb_device`.`id` = `clb_pricing_group_devices`.`device_id` and clb_pricing_group_devices.is_active = 1 
LEFT JOIN `clb_pricing_spec_grouping` ON `clb_pricing_group_devices`.`pricing_spec_id` = `clb_pricing_spec_grouping`.`pricing_master_spec_id` LEFT JOIN `clb_pricing_specifications` ON 
`clb_pricing_spec_grouping`.`pricing_spec_id` = `clb_pricing_specifications`.`id` WHERE clb_company.vendor_id is not null AND cast(substr(clb_devi
ce.software_version, 1, 3) as decimal(2,1)) > 2.0 AND clb_device.device_state > 0 GROUP BY `clb_device`.`id` ORDER BY CONCAT(trim(clb_company.portal_line1), `'/'`, trim(clb_device.name)) desc LIMIT 20

查看 CONCAT(trim(clb_company.portal_line1), `'/'`, trim(clb_device.name))

请提出解决方法。

Previously my all queries were running fine in CI version 2.0 but when I upgraded to 2.0.3 some of my SELECT queries were broken.

CI is adding backticks (``) automatically, but in older version its running as it is.

CI user manual have instructed to add second parameter in

db->select

as

FALSE

but still it's not working.

Code is as following:

class Company_model extends MY_Model
{

----------------

$this->db->select(' count('.$fieldname. ') as num_stations');
$this->db->select(" CONCAT_WS(',', clb_company.address1, clb_company.address2, clb_company.city, clb_company.state, clb_company.zipcode ) as companyAddress");
$this->db->from($this->_table);
$this->db->join($this->_table_device, $fieldname1. " = ".  $fieldname2, 'LEFT');
$this->db->where($blablafield , '0');
----------------

The error is as follows:

Error Number: 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 
'FROM (`clb_device`) JOIN `clb_company` ON `clb_company`.`id` = `clb_device`.`com' at line 2

SELECT `clb_device`.`id` as deviceId, `clb_pricing_specifications`.`name` as pricingSpecName, `clb_company`.`name` as companyName, `clb_device`.`mac_address` as deviceMacAddress, 
`clb_device`.`reseller_model_number` as deviceModelNumber, `clb_pricing_spec_grouping`.`pricing_master_spec_id` as pricingSpecId, `clb_device`.`address` as deviceAddress, 
`clb_device`.`is_home` as deviceIsHomeCharger, CONCAT(clb_company.portal_line1, `'/'`, `clb_device`.`name)` as deviceDisplayName FROM (`clb_device`) JOIN `clb_company` 
ON `clb_company`.`id` = `clb_device`.`company_id` LEFT JOIN `clb_pricing_group_devices` ON `clb_device`.`id` = `clb_pricing_group_devices`.`device_id` and clb_pricing_group_devices.is_active = 1 
LEFT JOIN `clb_pricing_spec_grouping` ON `clb_pricing_group_devices`.`pricing_spec_id` = `clb_pricing_spec_grouping`.`pricing_master_spec_id` LEFT JOIN `clb_pricing_specifications` ON 
`clb_pricing_spec_grouping`.`pricing_spec_id` = `clb_pricing_specifications`.`id` WHERE clb_company.vendor_id is not null AND cast(substr(clb_devi
ce.software_version, 1, 3) as decimal(2,1)) > 2.0 AND clb_device.device_state > 0 GROUP BY `clb_device`.`id` ORDER BY CONCAT(trim(clb_company.portal_line1), `'/'`, trim(clb_device.name)) desc LIMIT 20

Have a look at CONCAT(trim(clb_company.portal_line1), `'/'`, trim(clb_device.name))

Please suggest the workaround.

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

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

发布评论

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

评论(9

没有你我更好 2024-12-12 11:43:00

这是一个对我有用的技巧。将此行替换

$this->db->join($this->_table_device, $fieldname1. " = ".  $fieldname2, 'LEFT');

为:

$this->db->join($this->_table_device, $fieldname1. " IN(".  $fieldname2 .")", 'LEFT');

这将防止 CI 逃离您的字段。它并不理想,但比其他选择要好。

Here's a trick that worked for me. Replace this line

$this->db->join($this->_table_device, $fieldname1. " = ".  $fieldname2, 'LEFT');

with this:

$this->db->join($this->_table_device, $fieldname1. " IN(".  $fieldname2 .")", 'LEFT');

this will prevent CI from escaping your field. It's not ideal but it's better than the alternatives.

柳絮泡泡 2024-12-12 11:43:00

我刚刚读了一个简单的解决方案...

我更改了 var $_escape_char 的值(system/database/drivers/mysql/mysql_driver.php,第 36 行..

它被

var $_escape_char = '`';

更改为

var $_escape_char = ' ';

,现在它可以工作了...但我是担心如果我造成任何安全问题..

谢谢

I just read a simple solution for this...

I changed the value of var $_escape_char (system/database/drivers/mysql/mysql_driver.php, line 36..

It was

var $_escape_char = '`';

Changed to

var $_escape_char = ' ';

and now it works... But i am affraid if I made any security issues..

Thanks

柠北森屋 2024-12-12 11:42:59

在查询之前使用此行:

$this->db->_protect_identifiers=false;

这将停止向构建的查询添加反引号。

Use this line before your query:

$this->db->_protect_identifiers=false;

This will stop adding backticks to the built query.

伤感在游骋 2024-12-12 11:42:59

解决方案很简单:
在数据库配置文件 (./application/config/database.php) 中,使用默认设置向数组添加一个新元素。

$db['default']['_protect_identifiers']= FALSE;

这个解决方案对我来说很有效,而且更加优雅和专业。

The solution is very simple:
In the database configuration file (./application/config/database.php) add a new element to array with default settings.

$db['default']['_protect_identifiers']= FALSE;

This solution is working for me and more elegant and professional.

一个人的夜不怕黑 2024-12-12 11:42:59

所有其他答案都非常旧,这个适用于 CI 2.1.4

// set this to false so that _protect_identifiers skips escaping:
$this->db->_protect_identifiers = FALSE;

// your order_by line:
$this -> db -> order_by('FIELD ( products.country_id, 2, 0, 1 )');

// important to set this back to TRUE or ALL of your queries from now on will be non-escaped:
$this->db->_protect_identifiers = TRUE;

All other answers are really old, this one works with CI 2.1.4

// set this to false so that _protect_identifiers skips escaping:
$this->db->_protect_identifiers = FALSE;

// your order_by line:
$this -> db -> order_by('FIELD ( products.country_id, 2, 0, 1 )');

// important to set this back to TRUE or ALL of your queries from now on will be non-escaped:
$this->db->_protect_identifiers = TRUE;
情魔剑神 2024-12-12 11:42:59
class Company_model extends MY_Model
{

----------------

$this->db->select(" count('$fieldname') as num_stations",false);
$this->db->select(" CONCAT_WS(',', clb_company.address1, clb_company.address2, clb_company.city, clb_company.state, clb_company.zipcode ) as companyAddress",false);
$this->db->from($this->_table);
$this->db->join($this->_table_device, $fieldname1. " = ".  $fieldname2, 'LEFT');
$this->db->where($blablafield , '0');
----------------

您所说的 false 是所需要的,您可以尝试上面的代码并将输出复制并粘贴给我们吗?

echo $this->db->last_query();

这将向我们展示数据库类正在创建什么,我们可以看到什么在起作用/ 什么不是。它可能是其他东西(您没有给出生成的错误,有时 sql 错误可能会产生误导。)

来自 docs

$this->db->select() 接受可选的第二个参数。如果您将其设置为FALSE,CodeIgniter 将不会尝试使用反引号保护您的字段或表名称。如果您需要复合选择语句,这非常有用。

class Company_model extends MY_Model
{

----------------

$this->db->select(" count('$fieldname') as num_stations",false);
$this->db->select(" CONCAT_WS(',', clb_company.address1, clb_company.address2, clb_company.city, clb_company.state, clb_company.zipcode ) as companyAddress",false);
$this->db->from($this->_table);
$this->db->join($this->_table_device, $fieldname1. " = ".  $fieldname2, 'LEFT');
$this->db->where($blablafield , '0');
----------------

The false you were talking about is what is needed, can you try the code above and copy and paste to us the output of

echo $this->db->last_query();

This will show us what the DB class is creating exactly and we can see whats working / what isn't. It may be something else (you haven't given the error from that is generated sometimes sql errors can be misleading.)

From the docs:

$this->db->select() accepts an optional second parameter. If you set it to FALSE, CodeIgniter will not try to protect your field or table names with backticks. This is useful if you need a compound select statement.

多孤肩上扛 2024-12-12 11:42:59

CI 只会保护您的 ACTIVE RECORD 调用,因此如果您正在运行 $this->db->query(); 您会没事的,并且根据注释,您应该可以安全地使用 AD像这样的调用来禁用反引号(不知道为什么你说它们不起作用,但我没有看到你的完整代码,所以我不能确定)

$this->db->select('(SELECT SUM(payments.amount) FROM payments WHERE payments.invoice_id=4') AS amount_paid', FALSE);
$query = $this->db->get('mytable');

确保 FALSE 不带单引号(使其成为字符串),并且它可能无法验证(未经我测试)。

CI will only protect your ACTIVE RECORD calls, so if you are running $this->db->query(); you will be fine, and based on the notes you should be safe with AD calls like so to disable backticks (not sure why you say they don't work, but I don't see your full code, so I can't be sure)

$this->db->select('(SELECT SUM(payments.amount) FROM payments WHERE payments.invoice_id=4') AS amount_paid', FALSE);
$query = $this->db->get('mytable');

make sure FALSE is without single quotes (makes it a string), and it might not validate (not tested by me).

梦里梦着梦中梦 2024-12-12 11:42:59

我认为你应该检查DB_driver.php文件,有一个名为protect_identifier的变量,重点是当你检查旧版本的CI时,你会发现新版本中缺少一个条件,转义变量是检查是否可为空,粘贴旧版本中的条件,就可以了

I think you should check DB_driver.php file, there is a variable named as protect_identifier, the point is when you will check with older version of CI, you will see that there is a condition which is missing in new version,escape variable which is checked for nullability, paste that condition from older version and you will be OK

长不大的小祸害 2024-12-12 11:42:59

CI_DB_active_record::where() 有第三个参数用于转义,这对我来说比打开和关闭更好 CI_DB_driver::_protect_identifiers

public function where($key, $value = NULL, $escape = TRUE)

不确定添加了哪个 CI 版本in.

HTH某人

CI_DB_active_record::where() has a third param for escaping, this has worked better for me than switching on and off CI_DB_driver::_protect_identifiers

public function where($key, $value = NULL, $escape = TRUE)

Not sure what CI version this was added in.

HTH someone

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