<?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