23

以前はすべてのクエリが CI バージョン 2.0 で問題なく動作していましたが、2.0.3にアップグレードすると一部の SELECT クエリが壊れました。

CIはバッククォート(``)を自動でつけていますが、古いバージョンではそのまま動いていました。

CI ユーザー マニュアルでは、2 番目のパラメーターを追加するように指示されています。

デシベル->選択

なので

間違い

しかし、まだ機能していません。

コードは次のとおりです。

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))を見てください。

回避策を提案してください。

4

9 に答える 9

32

クエリの前に次の行を使用します。

$this->db->_protect_identifiers=false;

これにより、ビルドされたクエリへのバックティックの追加が停止します。

于 2013-01-09T09:48:14.423 に答える
15

解決策は非常に簡単です。データベース構成ファイル (./application/config/database.php) で、デフォルト設定の新しい要素を配列に追加します。

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

このソリューションは私にとっては機能しており、よりエレガントでプロフェッショナルです。

于 2012-06-07T22:04:59.113 に答える
7

他のすべての回答は非常に古いものです。これは 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;
于 2013-09-11T19:00:32.337 に答える
3
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();

これにより、DBクラスが正確に作成しているものが表示され、何が機能しているか、何が機能していないかがわかります。それは別のものである可能性があります(生成されたエラーを指定していない場合、SQLエラーが誤解を招く可能性があります)。

ドキュメントから:

$this->db->select()オプションの2番目のパラメーターを受け入れます。に設定するとFALSE、CodeIgniterはフィールド名またはテーブル名をバッククォートで保護しようとしません。これは、複合selectステートメントが必要な場合に役立ちます。

于 2011-09-28T19:35:38.977 に答える
2

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してください(文字列にします)。検証されない場合があります(私はテストしていません)。

于 2011-09-20T13:59:38.913 に答える
1

DB_driver.php ファイルを確認する必要があると思います。protect_identifier という名前の変数があります。ポイントは、古いバージョンの CI で確認すると、新しいバージョンでは欠落している条件があることがわかります。 Null可能性をチェックし、その条件を古いバージョンから貼り付ければ問題ありません

于 2011-09-29T15:14:45.850 に答える
0

これが私のために働いたトリックです。この行を置き換えます

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

これとともに:

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

これにより、CI がフィールドをエスケープできなくなります。理想的ではありませんが、代替案よりも優れています。

于 2011-12-16T14:46:22.663 に答える
-1

これに対する簡単な解決策を読んだだけです...

var $_escape_char の値を変更しました (system/database/drivers/mysql/mysql_driver.php、36 行目..

そうだった

var $_escape_char = '`';

に変更

var $_escape_char = ' ';

そして今では動作します...しかし、セキュリティ上の問題が発生した場合は恐れ入ります..

ありがとう

于 2011-10-01T06:13:30.813 に答える