Partilhar via


Funções definidas pelo utilizador

A maioria dos bancos de dados tem um dialeto processual de SQL que você pode usar para definir suas próprias funções. No entanto, o SQLite é executado em processo com seu aplicativo. Em vez de ter que aprender um novo dialeto de SQL, você pode simplesmente usar a linguagem de programação do seu aplicativo.

Funções escalares

As funções escalares retornam um único valor escalar para cada linha de uma consulta. Defina novas funções escalares e substitua as funções internas usando CreateFunction.

Consulte Tipos de dados para obter uma lista de parâmetros suportados e tipos de retorno para o func argumento.

Especificar o state argumento passará esse valor para cada invocação da função. Utilize-o para evitar encerramentos.

Especifique isDeterministic se sua função é determinística para permitir que o SQLite use otimizações adicionais ao compilar consultas.

O exemplo a seguir mostra como adicionar uma função escalar para calcular o raio de um cilindro.

connection.CreateFunction(
    "volume",
    (double radius, double height)
        => Math.PI * Math.Pow(radius, 2) * height);

var command = connection.CreateCommand();
command.CommandText =
@"
    SELECT name,
           volume(radius, height) AS volume
    FROM cylinder
    ORDER BY volume DESC
";

Operadores

Os seguintes operadores SQLite são implementados por funções escalares correspondentes. Definir essas funções escalares em seu aplicativo substituirá o comportamento desses operadores.

Operador Função
X GLOB Y glob(Y, X)
X COMO Y gostar(Y, X)
X COMO Y ESCAPE Z like(Y, X, Z)
X CONFORMAR Y associar(Y, X)
X REGEXP Y regexp (Y, X)

O exemplo a seguir mostra como definir a função regexp para habilitar seu operador correspondente. SQLite não inclui uma implementação padrão da função regexp.

connection.CreateFunction(
    "regexp",
    (string pattern, string input)
        => Regex.IsMatch(input, pattern));

var command = connection.CreateCommand();
command.CommandText =
@"
    SELECT count()
    FROM user
    WHERE bio REGEXP '\w\. {2,}\w'
";
var count = command.ExecuteScalar();

Funções agregadas

As funções de agregação retornam um único valor agregado para todas as linhas de uma consulta. Defina e redefina funções agregadas usando CreateAggregate.

O seed argumento especifica o estado inicial do contexto. Use isso para evitar fechamentos também.

O func argumento é invocado uma vez por linha. Use o contexto para obter um resultado final. Retorne o contexto. Esse padrão permite que o contexto seja um tipo de valor ou imutável.

Se resultSelector não estiver especificado, o estado final do contexto será usado como resultado. Isso pode simplificar a definição de funções como soma e contagem que só precisam incrementar um número em cada linha e retorná-lo.

Especifique resultSelector para calcular o resultado final a partir do contexto depois de iterar por todas as linhas.

Consulte Tipos de dados para obter uma lista de tipos de parâmetros suportados para o func argumento e tipos de retorno para resultSelector.

Se sua função for determinística, especifique isDeterministic para permitir que o SQLite use otimizações adicionais ao compilar consultas.

O exemplo a seguir define uma função de agregação para calcular o desvio padrão de uma coluna.

connection.CreateAggregate(
    "stdev",

    // A tuple to maintain context between rows
    (Count: 0, Sum: 0.0, SumOfSquares: 0.0),

    // This is called for each row
    ((int Count, double Sum, double SumOfSquares) context, double value) =>
    {
        context.Count++;
        context.Sum += value;
        context.SumOfSquares += value * value;

        return context;
    },

    // This is called to get the final result
    context =>
    {
        var variance = context.SumOfSquares - context.Sum * context.Sum / context.Count;

        return Math.Sqrt(variance / context.Count);
    });

var command = connection.CreateCommand();
command.CommandText =
@"
    SELECT stdev(gpa)
    FROM student
";
var stdDev = command.ExecuteScalar();

Erros

Se uma função definida pelo usuário lançar uma exceção, a mensagem será retornada para SQLite. SQLite gerará um erro e Microsoft.Data.Sqlite lançará um SqliteException. Para obter mais informações, consulte Erros de banco de dados.

Por padrão, o código de erro SQLite de erro será SQLITE_ERROR (ou 1). Você pode, no entanto, alterá-lo lançando um SqliteException na sua função com o SqliteErrorCode desejado especificado.

Depuração de código

SQLite invoca a sua implementação diretamente. Isso permite adicionar pontos de interrupção que são acionados enquanto o SQLite está avaliando consultas. A experiência completa de depuração do .NET está disponível para ajudá-lo a criar suas funções definidas pelo usuário.

Ver também