(Parte 6 de 13)

O item_group_by não pode ser uma referência a uma função agregada (incluindo qualquer uma que esteja localizada dentro da expressão) do mesmo contexto.

HAVING A cláusula HAVING apenas permite funções agregadas ou expressões válidas que façam parte da cláusula GROUP BY. Anteriormente era permitido utilizar colunas que não faziam parte da cláusula GROUP BY e utilizar expressões não-válidas.

ORDER BY No contexto de um comando agregado, a cláusula ORDER BY permite apenas expressões válidas que sejam funções agregadas ou partes de expressões que estejam na cláusula GROUP BY. Antigamente, era permitido usar expressões não-válidas.

Funções Agregadas em “subqueries” É agora possível utilizar em “subqueries” uma função agregada ou expressão contida numa cláusula GROUP BY.

r.RDB$RELATION_NAME,
MAX(r.RDB$FIELD_POSITION),
(SELECT
r2.RDB$FIELD_NAME
FROM
RDB$RELATION_FIELDS r2
WHERE
r2.RDB$RELATION_NAME = r.RDB$RELATION_NAME and
r2.RDB$FIELD_POSITION = MAX(r.RDB$FIELD_POSITION))
RDB$RELATION_FIELDS r
1

Exemplos SELECT FROM GROUP BY

rf.RDB$RELATION_NAME AS "Relationname",
(SELECT
r.RDB$RELATION_ID
FROM
RDB$RELATIONS r
WHERE
r.RDB$RELATION_NAME = rf.RDB$RELATION_NAME) AS "ID",
COUNT(*) AS "Fields"

SELECT FROM RDB$RELATION_FIELDS rf v.1.08 Notas da Versão Firebird 1.5 08 fevereiro 2004 Página 21

rf.RDB$RELATION_NAME

Misturando funções agregadas de diferentes contextos As funções agregadas de diferentes contextos podem ser utilizadas dentro de uma expressão.

r.RDB$RELATION_NAME,
MAX(i.RDB$STATISTICS) AS "Max1",
(SELECT
COUNT(*) || ' - ' || MAX(i.RDB$STATISTICS)
FROM
RDB$RELATION_FIELDS rf
WHERE
rf.RDB$RELATION_NAME = r.RDB$RELATION_NAME) AS "Max2"
RDB$RELATIONS r
JOIN RDB$INDICES i on (i.RDB$RELATION_NAME = r.RDB$RELATION_NAME)
r.RDB$RELATION_NAME
MIN(i.RDB$STATISTICS) <> MAX(i.RDB$STATISTICS)

Exemplo SELECT FROM GROUP BY HAVING Nota! Esta query retorna valores no FB1.0, mas eles são incorretos!

Subqueries são suportadas numa Função Agregada O uso de um “singleton select” (que devolve apenas uma linha) numa função agregada é agora suportado.

r.RDB$RELATION_NAME,
SUM((SELECT
COUNT(*)
FROM
RDB$RELATION_FIELDS rf
WHERE
rf.RDB$RELATION_NAME = r.RDB$RELATION_NAME))
RDB$RELATIONS r
JOIN RDB$INDICES i on (i.RDB$RELATION_NAME = r.RDB$RELATION_NAME)
r.RDB$RELATION_NAME

Exemplo SELECT FROM GROUP BY

Funções agregadas “Nested” A utilização de uma função agregada dentro de outra função agregada (nested) é possível se a função agregada interna for de um contexto inferior (ver exemplo).

Grau de Group By (ordinal) A utilização do número do grau da coluna de retorno na cláusula ‘GROUP BY’ “reproduz” a expressão da lista do select (à semelhança da cláusula ORDER BY). Isto faz com que, se o grau se refere a uma subquery, esta subquery seja executada pelo menos duas vezes.

v.1.08 Notas da Versão Firebird 1.5 08 fevereiro 2004 Página 2

(1.5) A Cláusula ORDER BY pode especificar expressões e localização dos NULL’s Nickolay Samofatov

A cláusula ORDER BY permite que se especifique qualquer expressão válida para ordenar os resultados da Query. Se a expressão consistir de um número, ele será interpretado como o grau da coluna, como previamente. A ordem dos nulos no resultado pode ser definida utilizando-se a cláusula de posicionamento dos nulos. Os resultados podem ser ordenados de forma que os nulos sejam posicionados antes (NULLS FIRST) ou depois (NULLS LAST) dos valores não nulos. Quando nada é especificado, a posição dos nulos é NULLS LAST.

SELECTFROM .... ORDER BY order_list ....;

Sintaxe order_list : order_item [, order_list]; order_item : <expressão> [order_diretion] [nulls_placement] order_diretion : ASC | DESC; nulls_placement : NULLS FIRST | NULLS LAST;

Restrições • Se for especificado NULLS FIRST, nenhum índice será utilizado na ordenação.

• Os resultados da ordenação de valores retornados por uma UDF ou Stored Procedure serão imprevisíveis se os valores retornados não puderem ser utilizados para determinar a sequência lógica de ordenação.

• O número de vezes que uma UDF ou Stored Procedure será acessado é indeterminado, não importando se a ordenação é especificada pela expressão propriamente ou por um número representando a expressão na lista de colunas do SQL.

• Uma cláusula de ordenação aplicada a uma query com union pode utilizar somente o número de grau (posicionamento) para se referir às colunas de ordenação.

Exemplos i) SELECT * FROM MSG ORDER BY PROCESS_TIME DESC NULLS FIRST i) SELECT FIRST 10 * FROM DOCUMENT ORDER BY STRLEN(DESCRIPTION) DESC i) SELECT DOC_NUMBER, DOC_DATE FROM PAYORDER UNION ALL SELECT DOC_NUMBER, DOC_DATA FROM BUDGORDER ORDER BY 2 DESC NULLS LAST, 1 ASC NULLS FIRST

PSQL ((Linguagem SQL para uso em Stored procedures e ttrriiggggerrss))

(1.5) EXECUTE STATEMENT Alex Peshkov v.1.08 Notas da Versão Firebird 1.5 08 fevereiro 2004 Página 23

Extensão ao PSQL que processa uma string que contém uma declaração SQL válida e a executa como se esta tivesse sido submetida ao DSQL. Disponível em triggers e stored procedures.

A Sintaxe pode ter três variantes.

Sintaxe 1 Executa <string> como uma declaração SQL que não devolve dados, por exemplo INSERT, UPDATE, DELETE, EXECUTE PROCEDURE ou qualquer declaração DDL exceto CREATE/DROP DATABASE.

EXECUTE STATEMENT <string>;

Exemplo

CREATE PROCEDURE ExemploDinamico1 (Pname VARCHAR(100)) AS DECLARE VARIABLE Sql VARCHAR(1024); DECLARE VARIABLE Par INT; BEGIN SELECT MIN(SomeField) FROM SomeTable INTO :Par; Sql = ’EXECUTE PROCEDURE ’ || Pname || ’(’; Sql = Sql || CAST(Par AS VARCHAR(20)) || ’)’; EXECUTE STATEMENT Sql; END

Sintaxe 2 Executa <string> como um comando SQL, que devolve apenas uma linha. Somente SELECTs que devolvam apenas uma única linha (“singleton”) podem ser utilizados com esta sintaxe.

EXECUTE STATEMENT <string> INTO :var1, […, :varn] ;

Exemplo

EXCEPTION Ex_Overflow ’Overflow in ’ || TableName;

CREATE PROCEDURE ExemploDinamico2 (TableName VARCHAR(100)) AS DECLARE VARIABLE Par INT; BEGIN EXECUTE STATEMENT ’SELECT MAX(CheckField) FROM ’ || TableName INTO :Par; IF (Par > 100) THEN END

Sintaxe 3 Executa <string> como um comando SQL, devolvendo várias linhas. Qualquer operador SELECT pode ser utilizado nesta variante.

FOR EXECUTE STATEMENT <string> INTO :var1, …, :varn DO <declaração composta>;

Exemplo

CREATE PROCEDURE DynamicSampleThree ( TextField VARCHAR(100), TableName VARCHAR(100)) RETURNING_VALUES (Line VARCHAR(32000)) AS v.1.08 Notas da Versão Firebird 1.5 08 fevereiro 2004 Página 24

IF (OneLine IS NOT NULL) THEN
Line = Line || OneLine || ’ ’;

DECLARE VARIABLE OneLine VARCHAR(100); BEGIN Line = ’’; FOR EXECUTE STATEMENT ’SELECT ’ || TextField || ’ FROM ’ || TableName INTO :OneLine DO SUSPEND; END

Notas adicionais ao uso de EXECUTE STATEMENT

A string DSQL do ‘EXECUTE STATEMENT’ não pode conter nenhum parâmetro em qualquer uma das suas formas de sintaxe. Todas as substituições de variáveis para o seu formato fixo devem ser efetuadas antes de se processar a declaração EXECUTE STATEMENT.

Esta funcionalidade deve ser utilizada com cautela, e após um exame cuidadoso de todos os fatores. Deve se observar como regra a utilização de um EXECUTE STATEMENT apenas quando outros métodos não são possíveis, ou quando a performance do EXECUTE STATMENT for a mais aceitável.

A declaração EXECUTE STATEMENT é potencialmente insegura nas seguintes condições:

1. Não existe forma de verificar a sintaxe correta da declaração contida na string. 2. Não são feitas verificações de dependência que possam garantir que tabela ou colunas requeridas não tenham sido destruídas. 3. As operações serão mais lentas porque o comando contido terá que ser preparado a cada execução. 4. Os valores devolvidos são verificados e restritos para cada tipo de dado, para evitar resultados imprevisíveis de conversão. Por exemplo, a string ‘1234’ seria convertida para um inteiro, 1234, mas ‘abc’ geraria um erro de conversão. 5. Se a Stored Procedure tiver privilégios especiais sobre alguns objetos, a declaração dinâmica submetida na string do EXECUTE STATEMENT não os herdará. Os privilégios serão restritos aos atribuídos ao usuário que executar a Stored Procedure.

(1.5) Novas variáveis de contexto Dmitry Yemanov

CURRENT_CONNECTION e

Cada uma destas novas variáveis de contexto devolve um identificador de sistema da conexão ativa e da transação corrente, respectivamente. O tipo devolvido é INTEGER. Disponível em PSQL e DSQL. Como estes valores são armazenados no cabeçalho do banco de dados, os seus valores serão zerados a cada “RESTORE” da base de dados.

Sintaxe CURRENT_CONNECTION CURRENT_TRANSACTION v.1.08 Notas da Versão Firebird 1.5 08 fevereiro 2004 Página 25

Exemplos

Retorna um inteiro, com o número de linhas afetadas pela última declaração DML. Disponível em PSQL, no contexto de uma trigger ou stored procedure. Na implementação atual, retorna zero para uma declaração SELECT.

Sintaxe ROW_COUNT

(Parte 6 de 13)

Comentários