Magento中直接使用SQL语句

原理:

magento是基于Zend Framework的,所以底层用的还是zend的zend db

在文件app/code/core/Mage/Catalog/model/Resource/Eav /Mysql4/Config.php 中追踪到下面的函数 getAttributesUsedInListing()

/**
* Retrieve Product Attributes Used in Catalog Product listing
*
* @return array
*/
public function getAttributesUsedInListing() {
$select = $this->_getReadAdapter()->select()
->from(array(’main_table’ => $this->getTable(’eav/attribute’)))
->join(
array(’additional_table’ => $this->getTable(’catalog/eav_attribute’)),
‘main_table.attribute_id = additional_table.attribute_id’,
array()
)
->joinLeft(
array(’al’ => $this->getTable(’eav/attribute_label’)),
‘al.attribute_id = main_table.attribute_id AND al.store_id = ‘ . (int) $this->getStoreId(),
array(’store_label’ => new Zend_Db_Expr(’IFNULL(al.value, main_table.frontend_label)’))
)
->where(’main_table.entity_type_id=?’, $this->getEntityTypeId())
->where(’additional_table.used_in_product_listing=?’, 1);
– $sql = $select->assemble();
– echo $sql;
return $this->_getReadAdapter()->fetchAll($select);
}

Magento操作数据库是在 Zend DB(Zend Framework)的基础上简单的做了下封装了。Zend DB 有自己的一套规则,来组合生成最终的SQL查询语句,可以看到上面的代码中有 from() join() joinLeft() where() 等函数,乱七八糟的一大堆东西,需要对 Zend DB的规则非常熟悉,才能知道实际执行的SQL语句,有没有办法直接打印出SQL语句?找了下,还真有,就是assemble()函数。在上面代码中最后 部分可以看到。顺被把SQL也附上来

SELECT `main_table`.*,
IFNULL(al.value, main_table.frontend_label) AS `store_label`
FROM `eav_attribute` AS `main_table`
INNER JOIN `catalog_eav_attribute` AS `additional_table`
ON main_table.attribute_id = additional_table.attribute_id
LEFT JOIN `eav_attribute_label` AS `al`
ON al.attribute_id = main_table.attribute_id AND al.store_id = 1
WHERE (main_table.entity_type_id=’4′)
AND (additional_table.used_in_product_listing=1)

Magento中打印SQL语句来调试

有时为了调试magento商城系统,需要获取当前的查询sql语句,magento中获取SQL语句,这里我们通过

$collection->getSelectSql(true)来调试sql

$collection=Mage::getResourceModel(‘reports/product_collection‘);
$query=$collection->getSelectSql(true);
echo $query;

magento获取SQL语句的另外一种方法是设置打印SQL为true

$collection=Mage::getResourceModel(‘reports/product_collection‘);
$collection->printlogquery(true);

得到的SQL语句

SELECT `e`.* FROM `catalog_product_entity` AS `e`

这里只是打印查询产品的SQL,如果要获取其他地方的SQL语句,道理也是一样的,我们根据上面的sql语句可以看到,其实magento的性能很差,"select *",magetno又是基于EAV架构的,可以想象下这速度

操作:

Magento的Models 和Collection 很强大,使用它们可以很方便的查询和操作数据库。但是有些场合,因为一些特殊需求或对Magento的了解不够深,可能会需要自己手写SQL语句来查询和操作数据库。以下分别是读写数据库的代码。

// For Read
// fetch read database connection that is used in Mage_Core module

$read= Mage::getSingleton(‘core/resource‘)->getConnection(‘core_read‘);

// first way
$query = $read->query("select name from core_website");
while ($row = $query->fetch())
{
    $row = new Varien_Object($row); 
    echo "<strong>" . $row->getName() . "</strong><br/>";
}

// second way
$results = $read->fetchAll("SELECT * FROM core_website;");
foreach ($results as $row)
{
    echo $row[‘name‘] . "<br/>"; 
}

// For Write
// fetch write database connection that is used in Mage_Core module
$write = Mage::getSingleton(‘core/resource‘)->getConnection(‘core_write‘);

// now $write is an instance of Zend_Db_Adapter_Abstract
$write->query("insert into tablename values (‘aaa‘,‘bbb‘,‘ccc‘)");

注意上面的getConnection()方法中的参数 "core_read",表明了Magento将要使用的资源。与之相对应,当我们修改数据库的时候使用参数"core_write".一般情况下 getConnection方法的参数应设成"core_read" 或 "core_write"(应该不指定也是可以的,但是如果Magento有多个数据库就必须指定了)。

作为新的entension module,在config.xml对"core_read" "core_write" 进行定义是个好的习惯。定义如下:

<config>
    <global>
        <resources>
            <extension_setup>
                <connection>
                    <use>core_setup</use>
                </connection>
            </extension_setup>
            <extension_read>
                <connection>
                    <use>core_read</use>
                </connection>
            </extension_read>
            <extension_write>
                <connection>
                    <use>core_write</use>
                </connection>
            </extension_write>
        </resources>
    </global>
</config>
对应上面新增的module的名字.使用下面相对应的语句在read或write Database:

$conn = Mage::getSingleton(‘core/resource‘)->getConnection(‘extension_read‘);
$conn = Mage::getSingleton(‘core/resource‘)->getConnection(‘extension_write‘);

一般情况是绝大多数的module都定义成"core_read" "core_write"方便且节省资源。当然特殊情况除外:

  • 给每个module不同的读写权限
  • 需要用多个Database

实例:

<?php
    /**
     * Get the resource model
     */
    $resource = Mage::getSingleton(‘core/resource‘);
 
    /**
     * Retrieve the read connection
     */
    $readConnection = $resource->getConnection(‘core_read‘);
 
    /**
     * Retrieve the write connection
     */
    $writeConnection = $resource->getConnection(‘core_write‘);

Get a table name from a string

<?php
 
    /**
     * Get the resource model
     */
    $resource = Mage::getSingleton(‘core/resource‘);
 
    /**
     * Get the table name
     */
    $tableName = $resource->getTableName(‘catalog_product_entity‘);
 
    /**
     * if prefix was ‘mage_‘ then the below statement
     * would print out mage_catalog_product_entity
     */
    echo $tableName;

Get a table name from an entity name

<?php
 
    /**
     * Get the resource model
     */
    $resource = Mage::getSingleton(‘core/resource‘);
 
    /**
     * Get the table name
     */
    $tableName = $resource->getTableName(‘catalog/product‘);
 
    /**
     * if prefix was ‘mage_‘ then the below statement
     * would print out mage_catalog_product_entity
     */
    echo $tableName;

Reading From The Database
Varien_Db_Select::fetchAll

This method takes a query as it‘s parameter, executes it and then returns all of the results as an array. In the code example below, we use Varien_Db_Select::fetchAll to return all of the records in the catalog_product_entity table.

<?php
 
    /**
     * Get the resource model
     */
    $resource = Mage::getSingleton(‘core/resource‘);
 
    /**
     * Retrieve the read connection
     */
    $readConnection = $resource->getConnection(‘core_read‘);
 
    $query = ‘SELECT * FROM ‘ . $resource->getTableName(‘catalog/product‘);
 
    /**
     * Execute the query and store the results in $results
     */
    $results = $readConnection->fetchAll($query);
 
    /**
     * Print out the results
     */
    echo sprintf(‘<pre>%s</pre>‘ print_r($results, true));

Varien_Db_Select::fetchCol

This method is similar to fetchAll except that instead of returning all of the results, it returns the first column from each result row. In the code example below, we use Varien_Db_Select::fetchCol to retrieve all of the SKU‘s in our database in an array.

<?php
    /**
      * Get the resource model
      */
    $resource = Mage::getSingleton(‘core/resource‘);
 
    /**
     * Retrieve the read connection
     */
    $readConnection = $resource->getConnection(‘core_read‘);
 
    /**
     * Retrieve our table name
     */
    $table = $resource->getTableName(‘catalog/product‘);
 
    /**
     * Execute the query and store the results in $results
     */
    $sku = $readConnection->fetchCol(‘SELECT sku FROM ‘ . $table . ‘);
 
    /**
     * Print out the results
     */
    echo sprintf(‘<pre>%s</pre>‘ print_r($results, true));

Try this code and look at the results. Notice how all of the SKU‘s are in a single array, rather than each row having it‘s own array? If you don‘t understand this, try changing fetchCol for fetchAll and compare the differences.

Varien_Db_Select::fetchOne

Unlike the previous two methods, Varien_Db_Select::fetchOne returns one value from the first row only. This value is returned on it‘s own and is not wrapped in an array. In the code example below, we take a product ID of 44 and return it‘s SKU.

<?php
 
    /**
     * Get the resource model
     */
    $resource = Mage::getSingleton(‘core/resource‘);
 
    /**
     * Retrieve the read connection
     */
    $readConnection = $resource->getConnection(‘core_read‘);
 
    /**
     * Retrieve our table name
     */
    $table = $resource->getTableName(‘catalog/product‘);
 
    /**
     * Set the product ID
     */
    $productId = 44;
 
    $query = ‘SELECT sku FROM ‘ . $table . ‘ WHERE entity_id = ‘
             . (int)$productId . ‘ LIMIT 1‘;
 
    /**
     * Execute the query and store the result in $sku
     */
    $sku = $readConnection->fetchOne($query);
 
    /**
     * Print the SKU to the screen
     */
    echo ‘SKU: ‘ . $sku . ‘<br/>‘;

When trying out this example, ensure you change the product ID to an ID that exists in your database!

You may think that fetchOne works the same as fetchCol or fetchAll would if you only added 1 column to the SELECT query and added a ‘LIMIT 1‘, however you would be wrong. The main difference with this function is that the value returned is the actual value, where as Varien_Db_Select::fetchCol and Varien_Db_Select::fetchAll would wrap the value in an array. To understand this a little, try swapping the method‘s and comparing the results.

Writing To The Database

When saving a Magento model, there can be a lot of background data being saved that you weren‘t even aware of. For example, saving a product model can take several seconds due to the amount of related data saves and indexing that needs to take place. This is okay if you need all the data saving, but if you only want to update the SKU of a product, this can be wasteful.

The example code below will show you how when given a product ID, you can alter the SKU. This is a trivial example but should illustrate how to execute write queries against your Magento database.

<?php
 
    /**
     * Get the resource model
     */
    $resource = Mage::getSingleton(‘core/resource‘);
 
    /**
     * Retrieve the write connection
     */
    $writeConnection = $resource->getConnection(‘core_write‘);
 
    /**
     * Retrieve our table name
     */
    $table = $resource->getTableName(‘catalog/product‘);
 
    /**
     * Set the product ID
     */
    $productId = 44;
 
    /**
     * Set the new SKU
     * It is assumed that you are hard coding the new SKU in
     * If the input is not dynamic, consider using the
     * Varien_Db_Select object to insert data
     */
    $newSku = ‘new-sku‘;
 
    $query = "UPDATE {$table} SET sku = ‘{$sku}‘ WHERE entity_id = "
             . (int)$productId;
 
    /**
     * Execute the query
     */
    $writeConnection->query($query);

To test this has worked, use the knowledge gained from the first part of this tutorial to write a query to extract the SKU that has just been changed.

Varien_Db_Select

The Varien_Db_Select, which has been touched on in this article is a far better option for extracting/wriiting information. Not only is it easy to use, it also provides a layered of security, which if used correctly, is impenetrable. More will be covered on Varien_Db_Select (aka Zend_Db_Select) in a future article.

时间: 2024-10-12 09:25:31

Magento中直接使用SQL语句的相关文章

Magento中如何调用SQL语句

I. 创建表结构和测试数据 create table rooms(id int not null auto_increment, name varchar(100), primary key(id));insert into rooms values(1,'Royal Room');insert into rooms values(2,'Standard Room'); II.创建 controllers/RoomController.php: 源码打印? <?php class Cartz_H

机房收费系统中遇到的SQL语句问题

个人版机房收费系统正在进行中,遇到了几个有关SQL语句的问题. 1.sum函数的使用: 在结账部分,要求出某个表中某一列的和.在第一次机房系统中,我不知道sum函数的存在,很傻很天真地用循环一个一个往上加.下面以求所有卡中余额的和来说说sum函数怎么使,SQL语句为:select sum(cash)from T_Card.这个格式不是固定的,可以根据需求更改,比如求多列的和:select sum(列名1),sum(列名2)...from [表名] where....查询出来的结果只有一行,如果只

SQL*PLUS中批量执行SQL语句

SQL*PLUS中批量执行SQL语句 今天由于工作的需要,要在CMD中批量执行大量的SQL语句,对于Oracle学习还处在入门阶段的我,只能硬着头皮到处去寻找资料(主要是网络资料,也包括自己的电子书),最后将所有的SQL语句一次性的执行完成. 首先,将要执行的所有的SQL语句,全部写入某个sql文件当中.例如f:\test.sql; 然后,通过通过sqlplus连接到数据库:如: SQL> sqlplus test/[email protected]; 再执行如下命令: SQL> @f:\te

查询EBS中LOV的SQL语句

帮助->关于 会话 SID : 507 DECLARE  l_sid NUMBER := :SID;BEGIN  FOR cur_sql IN (SELECT sql_text                    FROM v$sqltext_with_newlines t                   WHERE t.address IN (SELECT s.prev_sql_addr                                         FROM v$ses

Mybatis中如何在SQL语句表名中使用参数

insert into prefix_${table_name} (a, b, c) values (#{a}, #{b}, #{c}) ${} 表示直接使用字面量(literal value) #{} 表示这个是个参数 如果 table_name 是 "ABC" 则 ${table_name} 是 ABC #{table_name} 是 "ABC" Mybatis中如何在SQL语句表名中使用参数,布布扣,bubuko.com

存储过程中执行动态Sql语句

存储过程中执行动态Sql语句 MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有.还有一个最大的好处就是利用sp_executesql,能够重用执行计划,这就大大提供了执行性能,还可以编写更安全的代码.EXEC在某些情况下会更灵活.除非您有令人信服的理由使用EXEC,否侧尽量使用sp_executesql. 1.EXEC的使用 EXEC命令有两种用法,一种是执行一个存储

grails中直接使用SQL语句

在grails中直接使用SQL语句进行查询,可以直接获取一个新连接,也可以使用默认的数据源 查询代码:       ApplicationContext ctx = (ApplicationContext) ApplicationHolder.getApplication().getMainContext()       def dataSource = ctx.getBean('dataSource')       def sql = new Sql(dataSource)       Str

SQL Server中常用的SQL语句(转):

SQL Server中常用的SQL语句 转自:http://www.cnblogs.com/rainman/archive/2013/05/04/3060428.html 1.概述 名词 笛卡尔积.主键.外键 数据完整性 实体完整性:主属性不能为空值,例如选课表中学号和课程号不能为空 参照完整性:表中的外键取值为空或参照表中的主键 用户定义完整性:取值范围或非空限制,例如:性别(男女),年龄(0-130) 表连接 自然连接:与等值连接(a.id=b.id)相比,连接后的表只有一列id,而不是两列

SQL点滴32—Excel中CONCATENATE函数生成SQL语句

原文:SQL点滴32-Excel中CONCATENATE函数生成SQL语句 当拿到一个Excel的时候需要将这里面的数据插入到数据库里面,该怎么办,除了使用SSIS数据导入之外还可以使用Excel中的CONCATENATE函数,这个有点技巧,第一次使用的时候可能会让你有点困惑.如果我们理解这个函数的定义就不难了. 定义 CONCATENATE 函数可将最多 255 个文本字符串合并为一个文本字符串.联接项可以是文本.数字.单元格引用或这些项的组合.例如,如果您的工作表的单元格 A1 中包含某个人