<?php namespace Laravel\Database\Query\Grammars;
use Laravel\Database\Query;
class SQLServer extends Grammar {
/**
* The keyword identifier for the database system.
* 数据库系统的关键字标识符。
* @var string
*/
protected $wrapper = '[%s]';
/**
* Compile a SQL SELECT statement from a Query instance.
* 从 Query 实例编译 SQL SELECT 语句。
* @param Query $query
* @return string
*/
public function select(Query $query)
{
$sql = parent::components($query);
// SQL Server does not currently implement an "OFFSET" type keyword, so we
// actually have to generate the ANSI standard SQL for doing offset like
// functionality. In the next version of SQL Server, an OFFSET like
// keyword is included for convenience.
// SQL Server 目前没有实现“OFFSET”类型的关键字,因此我们实际上必须生成 ANSI 标准 SQL 来执行类似偏移的功能。
// 在下一版本的 SQL Server 中,为方便起见,包含了一个类似 OFFSET 的关键字。
if ($query->offset > 0)
{
return $this->ansi_offset($query, $sql);
}
// Once all of the clauses have been compiled, we can join them all as
// one statement. Any segments that are null or an empty string will
// be removed from the array of clauses before they are imploded.
// 一旦编译了所有子句,我们就可以将它们全部连接为一个语句。 任何为 null 或空字符串的段都将在它们内爆之前从子句数组中删除。
return $this->concatenate($sql);
}
/**
* Compile the SELECT clause for a query.
* 为查询编译 SELECT 子句。
* @param Query $query
* @return string
*/
protected function selects(Query $query)
{
if ( ! is_null($query->aggregate)) return;
$select = ($query->distinct) ? 'SELECT DISTINCT ' : 'SELECT ';
// Instead of using a "LIMIT" keyword, SQL Server uses the "TOP"
// keyword within the SELECT statement. So, if we have a limit,
// we will add it here.
// SQL Server 不使用“LIMIT”关键字,而是在 SELECT 语句中使用“TOP”关键字。 所以,如果我们有一个限制,我们会在这里添加它。
// We will not add the TOP clause if there is an offset however,
// since we will have to handle offsets using the ANSI syntax
// and will need to remove the TOP clause in that situation.
// 但是,如果存在偏移,我们将不会添加 TOP 子句,因为我们必须使用 ANSI 语法处理偏移,并且在这种情况下需要删除 TOP 子句。
if ($query->limit > 0 and $query->offset <= 0)
{
$select .= 'TOP '.$query->limit.' ';
}
return $select.$this->columnize($query->selects);
}
/**
* Generate the ANSI standard SQL for an offset clause.
* 为偏移子句生成 ANSI 标准 SQL。
* @param Query $query
* @param array $components
* @return array
*/
protected function ansi_offset(Query $query, $components)
{
// An ORDER BY clause is required to make this offset query
// work, so if one doesn't exist, we'll just create a dummy
// clause to satisfy the database.
// 需要一个 ORDER BY 子句来使这个偏移查询工作,所以如果一个不存在,我们将只创建一个虚拟子句来满足数据库。
if ( ! isset($components['orderings']))
{
$components['orderings'] = 'ORDER BY (SELECT 0)';
}
// We need to add the row number to the query results so we
// can compare it against the offset and limit values given
// for the statement. To do that we'll add an expression to
// the select statement for the row number.
// 我们需要将行号添加到查询结果中,以便我们可以将其与为语句给出的偏移量和限制值进行比较。
// 为此,我们将为行号的 select 语句添加一个表达式。
$orderings = $components['orderings'];
$components['selects'] .= ", ROW_NUMBER() OVER ({$orderings}) AS RowNum";
unset($components['orderings']);
$start = $query->offset + 1;
// Next we need to calculate the constraint that should be
// placed on the row number to get the correct offset and
// limit on the query. If a limit has not been set, we'll
// only add a constraint to handle offset.
// 接下来我们需要计算应该放在行号上的约束,以获得正确的偏移量和查询限制。 如果尚未设置限制,我们将只添加一个约束来处理偏移。
if ($query->limit > 0)
{
$finish = $query->offset + $query->limit;
$constraint = "BETWEEN {$start} AND {$finish}";
}
else
{
$constraint = ">= {$start}";
}
// Now, we're finally ready to build the final SQL query.
// We'll create a common table expression with the query
// and then select all of the results from it where the
// row number is between oru given limit and offset.
// 现在,我们终于准备好构建最终的 SQL 查询了。
// 我们将使用查询创建一个公共表表达式,然后从中选择行号在 oru 给定限制和偏移量之间的所有结果。
$sql = $this->concatenate($components);
return "SELECT * FROM ($sql) AS TempTable WHERE RowNum {$constraint}";
}
/**
* Compile the LIMIT clause for a query.
* 为查询编译 LIMIT 子句。
* @param Query $query
* @return string
*/
protected function limit(Query $query)
{
return '';
}
/**
* Compile the OFFSET clause for a query.
* 为查询编译 OFFSET 子句。
* @param Query $query
* @return string
*/
protected function offset(Query $query)
{
return '';
}
}
github地址: https://github.com/liu-shilong/laravel3-scr