CMssqlCommandBuilder
包 | system.db.schema.mssql |
---|---|
继承 | class CMssqlCommandBuilder » CDbCommandBuilder » CComponent |
版本 | $Id: CMssqlCommandBuilder.php 3515 2011-12-28 12:29:24Z mdomba $ |
源码 | framework/db/schema/mssql/CMssqlCommandBuilder.php |
公共属性
隐藏继承属性
属性 | 类型 | 描述 | 定义在 |
---|---|---|---|
dbConnection | CDbConnection | database connection. | CDbCommandBuilder |
schema | CDbSchema | the schema for this command builder. | CDbCommandBuilder |
公共方法
隐藏继承方法
方法 | 描述 | 定义在 |
---|---|---|
__call() | 如果类中没有调的方法名,则调用这个方法。 | CComponent |
__construct() | CDbCommandBuilder | |
__get() | 返回一个属性值、一个事件处理程序列表或一个行为名称。 | CComponent |
__isset() | 检查一个属性是否为null。 | CComponent |
__set() | 设置一个组件的属性值。 | CComponent |
__unset() | 设置一个组件的属性为null。 | CComponent |
applyCondition() | Alters the SQL to apply WHERE clause. | CDbCommandBuilder |
applyGroup() | Alters the SQL to apply GROUP BY. | CDbCommandBuilder |
applyHaving() | Alters the SQL to apply HAVING. | CDbCommandBuilder |
applyJoin() | Alters the SQL to apply JOIN clause. | CDbCommandBuilder |
applyLimit() | This is a port from Prado Framework. | CMssqlCommandBuilder |
applyOrder() | Alters the SQL to apply ORDER BY. | CDbCommandBuilder |
asa() | 返回这个名字的行为对象。 | CComponent |
attachBehavior() | 附加一个行为到组件。 | CComponent |
attachBehaviors() | 附加一个行为列表到组件。 | CComponent |
attachEventHandler() | 为事件附加一个事件处理程序。 | CComponent |
bindValues() | Binds parameter values for an SQL command. | CDbCommandBuilder |
canGetProperty() | 确定属性是否可读。 | CComponent |
canSetProperty() | 确定属性是否可写。 | CComponent |
createColumnCriteria() | Creates a query criteria with the specified column values. | CDbCommandBuilder |
createCountCommand() | 为一个表创建COUNT(*)语句。 | CMssqlCommandBuilder |
createCriteria() | Creates a query criteria. | CDbCommandBuilder |
createDeleteCommand() | 创建DELETE语句。 | CMssqlCommandBuilder |
createFindCommand() | 为一个表创建SELECT语句。 | CMssqlCommandBuilder |
createInCondition() | Generates the expression for selecting rows of specified primary key values. | CDbCommandBuilder |
createInsertCommand() | Creates an INSERT command. | CDbCommandBuilder |
createPkCondition() | Generates the expression for selecting rows of specified primary key values. | CDbCommandBuilder |
createPkCriteria() | Creates a query criteria with the specified primary key. | CDbCommandBuilder |
createSearchCondition() | Generates the expression for searching the specified keywords within a list of columns. | CDbCommandBuilder |
createSqlCommand() | Creates a command based on a given SQL statement. | CDbCommandBuilder |
createUpdateCommand() | 创建UPDATE语句。 | CMssqlCommandBuilder |
createUpdateCounterCommand() | 创建递增或递减特定列的UPDATE语句。 | CMssqlCommandBuilder |
detachBehavior() | 从组件中分离一个行为。 | CComponent |
detachBehaviors() | 从组件中分离所有行为。 | CComponent |
detachEventHandler() | 分离一个存在的事件处理程序。 | CComponent |
disableBehavior() | 禁用一个附加行为。 | CComponent |
disableBehaviors() | 禁用组件附加的所有行为。 | CComponent |
enableBehavior() | 启用一个附加行为。 | CComponent |
enableBehaviors() | 启用组件附加的所有行为。 | CComponent |
evaluateExpression() | 计算一个PHP表达式,或根据组件上下文执行回调。 | CComponent |
getDbConnection() | 返回database connection. | CDbCommandBuilder |
getEventHandlers() | 返回一个事件的附加处理程序列表。 | CComponent |
getLastInsertID() | Returns the last insertion ID for the specified table. | CDbCommandBuilder |
getSchema() | 返回the schema for this command builder. | CDbCommandBuilder |
hasEvent() | 确定一个事件是否定义。 | CComponent |
hasEventHandler() | 检查事件是否有附加的处理程序。 | CComponent |
hasProperty() | 确定属性是否被定义。 | CComponent |
raiseEvent() | 发起一个事件。 | CComponent |
受保护方法
隐藏继承方法
方法 | 描述 | 定义在 |
---|---|---|
checkCriteria() | 检查使用offset或limit的查询条件是否有order by子句。 | CMssqlCommandBuilder |
createCompositeInCondition() | 生成根据指定符合键值选择行的表达式。 | CMssqlCommandBuilder |
ensureTable() | Checks if the parameter is a valid table schema. | CDbCommandBuilder |
findOrdering() | 基于简化语法:http://msdn2.microsoft.com/en-us/library/aa259187(SQL.80).aspx | CMssqlCommandBuilder |
joinOrdering() | CMssqlCommandBuilder | |
reverseDirection() | CMssqlCommandBuilder | |
rewriteLimitOffsetSql() | 为MSSQL数据库重写SQL以应用$limit > 0和$offset > 0。 | CMssqlCommandBuilder |
方法详细
applyLimit() 方法public string applyLimit(string $sql, integer $limit, integer $offset) | ||
$sql | string | SQL查询字符串 |
$limit | integer | 最大行数,若为-1则忽略limit。 |
$offset | integer | 行偏移,若为-1则忽略offset。 |
{return} | string | 带有limit和offset的SQL。 |
publicfunctionapplyLimit($sql,$limit,$offset)
{
$limit=$limit!==null?intval($limit):-1;
$offset=$offset!==null?intval($offset):-1;
if($limit>0&&$offset<=0)//justlimit
$sql=preg_replace('/^([s(])*SELECT(DISTINCT)?(?!s*TOPs*()/i',"\1SELECT\2TOP$limit",$sql);
elseif($limit>0&&$offset>0)
$sql=$this->rewriteLimitOffsetSql($sql,$limit,$offset);
return$sql;
}
This is a port from Prado Framework.
重写父类的实现。改变SQL以应用$limit和$offset。 应用带有offset的limit是根据SQL语句结构的 许多假设通过动态修改SQL实现的。 根据下面地址的附注完成修改: http://troels.arvin.dk/db/rdbms/#select-limit-offsetSELECT * FROM ( SELECT TOP n * FROM ( SELECT TOP z columns -- (z=n+skip) FROM tablename ORDER BY key ASC ) AS FOO ORDER BY key DESC -- ('FOO' may be anything) ) AS BAR ORDER BY key ASC -- ('BAR' may be anything)
Regular expressions are used to alter the SQL query. The resulting SQL query may be malformed for complex queries. The following restrictions apply
- In particular, commas should NOT be used as part of the ordering expression or identifier. Commas must only be used for separating the ordering clauses.
- In the ORDER BY clause, the column name should NOT be be qualified with a table name or view name. Alias the column names or use column index.
- No clauses should follow the ORDER BY clause, e.g. no COMPUTE or FOR clauses. checkCriteria() 方法
protected CDbCrireria checkCriteria(CMssqlTableSchema $table, CDbCriteria $criteria) | ||
$table | CMssqlTableSchema | 表schema |
$criteria | CDbCriteria | 查询条件 |
{return} | CDbCrireria | 修改后的查询条件 |
protectedfunctioncheckCriteria($table,$criteria)
{
if($criteria->offset>0&&$criteria->order==='')
{
$criteria->order=is_array($table->primaryKey)?implode(',',$table->primaryKey):$table->primaryKey;
}
return$criteria;
}
检查使用offset或limit的查询条件是否有order by子句。 重写父类的实现以检查带有offset的查询中order by子句是否已指定。 若未指定order by子句,则按主键排序。
createCompositeInCondition() 方法protected string createCompositeInCondition(CDbTableSchema $table, array $values, string $prefix) | ||
$table | CDbTableSchema | 表schema |
$values | array | 要选择的主键值列表 |
$prefix | string | 列前缀(以.结束) |
{return} | string | 选择的表达式。 |
protectedfunctioncreateCompositeInCondition($table,$values,$prefix)
{
$vs=array();
foreach($valuesas$value)
{
$c=array();
foreach($valueas$k=>$v)
$c[]=$prefix.$table->columns[$k]->rawName.'='.$v;
$vs[]='('.implode('AND',$c).')';
}
return'('.implode('OR',$vs).')';
}
生成根据指定符合键值选择行的表达式。
createCountCommand() 方法public CDbCommand createCountCommand(CDbTableSchema $table, CDbCriteria $criteria, string $alias='t') | ||
$table | CDbTableSchema | 表元数据。 |
$criteria | CDbCriteria | 查询条件。 |
$alias | string | 主表的别名。默认为‘t’。 |
{return} | CDbCommand | 查询语句。 |
publicfunctioncreateCountCommand($table,$criteria,$alias='t')
{
$criteria->order='';
returnparent::createCountCommand($table,$criteria,$alias);
}
为一个表创建COUNT(*)语句。 重写父类的实现以移除条件里的order子句(如果它存在)。
createDeleteCommand() 方法public CDbCommand createDeleteCommand(CDbTableSchema $table, CDbCriteria $criteria) | ||
$table | CDbTableSchema | 表元数据 |
$criteria | CDbCriteria | 查询条件 |
{return} | CDbCommand | delete语句。 |
publicfunctioncreateDeleteCommand($table,$criteria)
{
$criteria=$this->checkCriteria($table,$criteria);
returnparent::createDeleteCommand($table,$criteria);
}
创建DELETE语句。 重写父类的实现以检查带有offset的查询中order by子句是否已指定。
createFindCommand() 方法public CDbCommand createFindCommand(CDbTableSchema $table, CDbCriteria $criteria, string $alias='t') | ||
$table | CDbTableSchema | 表元数据。 |
$criteria | CDbCriteria | 查询条件。 |
$alias | string | 主表的别名。默认为‘t’。 |
{return} | CDbCommand | 查询语句。 |
publicfunctioncreateFindCommand($table,$criteria,$alias='t')
{
$criteria=$this->checkCriteria($table,$criteria);
returnparent::createFindCommand($table,$criteria,$alias);
}
为一个表创建SELECT语句。 重写父类的实现以检查带有offset的查询中order by子句是否已指定。
createUpdateCommand() 方法public CDbCommand createUpdateCommand(CDbTableSchema $table, array $data, CDbCriteria $criteria) | ||
$table | CDbTableSchema | 表元数据。 |
$data | array | 要更新的列(名=>值) |
$criteria | CDbCriteria | 查询条件 |
{return} | CDbCommand | update语句。 |
publicfunctioncreateUpdateCommand($table,$data,$criteria)
{
$criteria=$this->checkCriteria($table,$criteria);
$fields=array();
$values=array();
$bindByPosition=isset($criteria->params[0]);
$i=0;
foreach($dataas$name=>$value)
{
if(($column=$table->getColumn($name))!==null)
{
if($table->sequenceName!==null&&$column->isPrimaryKey===true)continue;
if($column->dbType==='timestamp')continue;
if($valueinstanceofCDbExpression)
{
$fields[]=$column->rawName.'='.$value->expression;
foreach($value->paramsas$n=>$v)
$values[$n]=$v;
}
elseif($bindByPosition)
{
$fields[]=$column->rawName.'=?';
$values[]=$column->typecast($value);
}
else
{
$fields[]=$column->rawName.'='.self::PARAM_PREFIX.$i;
$values[self::PARAM_PREFIX.$i]=$column->typecast($value);
$i++;
}
}
}
if($fields===array())
thrownewCDbException(Yii::t('yii','Nocolumnsarebeingupdatedfortable"{table}".',
array('{table}'=>$table->name)));
$sql="UPDATE{$table->rawName}SET".implode(',',$fields);
$sql=$this->applyJoin($sql,$criteria->join);
$sql=$this->applyCondition($sql,$criteria->condition);
$sql=$this->applyOrder($sql,$criteria->order);
$sql=$this->applyLimit($sql,$criteria->limit,$criteria->offset);
$command=$this->getDbConnection()->createCommand($sql);
$this->bindValues($command,array_merge($values,$criteria->params));
return$command;
}
创建UPDATE语句。 重写父类的实现因为MSSQL不希望更新标识列。
createUpdateCounterCommand() 方法public CDbCommand createUpdateCounterCommand(CDbTableSchema $table, CDbCriteria $counters, array $criteria) | ||
$table | CDbTableSchema | 表元数据 |
$counters | CDbCriteria | 查询条件 |
$criteria | array | 要更新的计数器(列名为索引的递增或递减计数器)。 |
{return} | CDbCommand | update语句。 |
publicfunctioncreateUpdateCounterCommand($table,$counters,$criteria)
{
$criteria=$this->checkCriteria($table,$criteria);
returnparent::createUpdateCounterCommand($table,$counters,$criteria);
}
创建递增或递减特定列的UPDATE语句。 重写父类的实现以检查带有offset的查询中order by子句是否已指定。
findOrdering() 方法protected array findOrdering(string $sql) | ||
$sql | string | $sql |
{return} | array | 排序表达式作为键及排序方向作为值。 |
protectedfunctionfindOrdering($sql)
{
if(!preg_match('/ORDERBY/i',$sql))
returnarray();
$matches=array();
$ordering=array();
preg_match_all('/(ORDERBY)[s"[](.*)(ASC|DESC)?(?:[s"[]|$|COMPUTE|FOR)/i',$sql,$matches);
if(count($matches)>1&&count($matches[2])>0)
{
$parts=explode(',',$matches[2][0]);
foreach($partsas$part)
{
$subs=array();
if(preg_match_all('/(.*)[s"]](ASC|DESC)$/i',trim($part),$subs))
{
if(count($subs)>1&&count($subs[2])>0)
{
$name='';
foreach(explode('.',$subs[1][0])as$p)
{
if($name!=='')
$name.='.';
$name.='['.trim($p,'[]').']';
}
$ordering[$name]=$subs[2][0];
}
//elsewhat?
}
else
$ordering[trim($part)]='ASC';
}
}
//replacingcolumnnameswiththeiraliasnames
foreach($orderingas$name=>$direction)
{
$matches=array();
$pattern='/s+'.str_replace(array('[',']'),array('[',']'),$name).'s+ASs+([[^]]+])/i';
preg_match($pattern,$sql,$matches);
if(isset($matches[1]))
{
$ordering[$matches[1]]=$ordering[$name];
unset($ordering[$name]);
}
}
return$ordering;
}
基于简化语法:http://msdn2.microsoft.com/en-us/library/aa259187(SQL.80).aspx
joinOrdering() 方法protected string joinOrdering(array $orders, string $newPrefix) | ||
$orders | array | 从findOrdering获得的order信息 |
$newPrefix | string | 加在排序列的新表前缀。 |
{return} | string | 连接后的order表达式。 |
protectedfunctionjoinOrdering($orders,$newPrefix)
{
if(count($orders)>0)
{
$str=array();
foreach($ordersas$column=>$direction)
$str[]=$column.''.$direction;
$orderBy='ORDERBY'.implode(',',$str);
returnpreg_replace('/s+[[^]]+].([[^]]+])/i',''.$newPrefix.'.1',$orderBy);
}
}
reverseDirection() 方法protected array reverseDirection(array $orders) | ||
$orders | array | 原始order信息 |
{return} | array | 反转方向的order信息。 |
protectedfunctionreverseDirection($orders)
{
foreach($ordersas$column=>$direction)
$orders[$column]=strtolower(trim($direction))==='desc'?'ASC':'DESC';
return$orders;
}
rewriteLimitOffsetSql() 方法protected sql rewriteLimitOffsetSql(string $sql, integer $limit, integer $offset) | ||
$sql | string | SQL查询 |
$limit | integer | $limit > 0 |
$offset | integer | $offset > 0 |
{return} | sql | 应用limit和offset的修改后SQL查询 |
protectedfunctionrewriteLimitOffsetSql($sql,$limit,$offset)
{
$fetch=$limit+$offset;
$sql=preg_replace('/^([s(])*SELECT(DISTINCT)?(?!s*TOPs*()/i',"\1SELECT\2TOP$fetch",$sql);
$ordering=$this->findOrdering($sql);
$orginalOrdering=$this->joinOrdering($ordering,'[__outer__]');
$reverseOrdering=$this->joinOrdering($this->reverseDirection($ordering),'[__inner__]');
$sql="SELECT*FROM(SELECTTOP{$limit}*FROM($sql)as[__inner__]{$reverseOrdering})as[__outer__]{$orginalOrdering}";
return$sql;
}
为MSSQL数据库重写SQL以应用$limit > 0和$offset > 0。 参见http://troels.arvin.dk/db/rdbms/#select-limit-offset