Construção de SQL no tempo de execução¶
O Snowflake aceita diversas técnicas diferentes para construir cadeias de caracteres de instruções SQL dinamicamente no tempo de execução. Ao usar essas técnicas, você pode especificar cadeias de caracteres SQL mais gerais e flexíveis para casos de uso em que o texto completo das instruções SQL é desconhecido até o tempo de execução.
Um procedimento armazenado ou aplicativo pode aceitar a entrada do usuário e então usar essa entrada em uma instrução SQL. Por exemplo, uma tabela pode armazenar informações sobre pedidos de vendas. Um aplicativo ou procedimento armazenado pode aceitar um ID de pedido como entrada e executar uma consulta que retorna apenas os resultados para aquele pedido específico.
Um desenvolvedor pode escrever um código de procedimento armazenado ou código de aplicativo com instruções SQL que contenham espaços reservados e, então, vincular variáveis a esses espaços reservados no código. Esses espaços reservados são chamados de variáveis de vinculação. Um desenvolvedor também pode escrever um código que constrói instruções SQL a partir de uma cadeia de caracteres de entrada (por exemplo, concatenando cadeias de caracteres que contêm um comando SQL, parâmetros e valores).
As seguintes técnicas estão disponíveis para construir instruções SQL dinamicamente no tempo de execução:
A função TO_QUERY - Esta função recebe uma cadeia de caracteres SQL com parâmetros opcionais como entrada.
SQL dinâmico - O código em um procedimento armazenado ou aplicativo recebe uma entrada e constrói uma instrução SQL dinâmica usando essa entrada. O código pode ser parte de um procedimento armazenado do Snowflake Scripting ou Javascript, ou de um bloco anônimo do Snowflake Scripting. Você também pode usar essa técnica no código do seu aplicativo que usa um driver Snowflake ou o REST API SQL Snowflake.
Nota
Quando programas constroem instruções SQL com a entrada do usuário, há riscos potenciais de segurança, como injeção SQL. Se as entradas nas instruções SQL vierem de fontes externas, certifique-se de que elas sejam validadas. Para obter mais informações, consulte Injeção de SQL.
Usar a função TO_QUERY¶
Você pode usar a função TO_QUERY no código para procedimentos armazenados e aplicativos que constroem instruções SQL dinamicamente. Essa função de tabela recebe uma cadeia de caracteres SQL como entrada. Opcionalmente, a cadeia de caracteres SQL pode conter parâmetros, e você pode especificar os argumentos a serem passados aos parâmetros como variáveis de vinculação.
A seguir está um exemplo simples que chama a função:
SELECT COUNT(*) FROM TABLE(TO_QUERY('SELECT 1'));
+----------+
| COUNT(*) |
|----------|
| 1 |
+----------+
O exemplo a seguir usa a função TO_QUERY em um procedimento armazenado:
CREATE OR REPLACE PROCEDURE get_num_results_tq(query VARCHAR)
RETURNS TABLE ()
LANGUAGE SQL
AS
DECLARE
res RESULTSET DEFAULT (SELECT COUNT(*) FROM TABLE(TO_QUERY(:query)));
BEGIN
RETURN TABLE(res);
END;
Observação: se você estiver usando o método SnowSQL, o Classic Console, execute_stream
ou execute_string
no código Python Connector, use este exemplo (consulte Uso do Script Snowflake em SnowSQL, Classic Console e conector Python):
CREATE OR REPLACE PROCEDURE get_num_results_tq(query VARCHAR)
RETURNS TABLE ()
LANGUAGE SQL
AS
$$
DECLARE
res RESULTSET DEFAULT (SELECT COUNT(*) FROM TABLE(TO_QUERY(:query)));
BEGIN
RETURN TABLE(res);
END;
$$
;
Chame o procedimento armazenado:
CALL get_num_results_tq('SELECT 1');
+----------+
| COUNT(*) |
|----------|
| 1 |
+----------+
Usar SQL dinâmico em procedimentos armazenados e aplicativos¶
Para construir instruções SQL que aceitam entrada do usuário, você pode usar SQL dinâmico em um procedimento armazenado do Snowflake Scripting ou Javascript, ou em um bloco anônimo do Snowflake Scripting. Você também pode usar SQL dinâmico no código do seu aplicativo que usa um driver Snowflake ou o REST API SQL Snowflake.
Esse exemplo cria um procedimento armazenado com o Snowflake Scripting. O procedimento armazenado recebe texto SQL como entrada e constrói uma cadeia de caracteres que contém uma instrução SQL anexando o texto a ela. O SQL dinâmico é então executado usando o comando EXECUTE IMMEDIATE.
CREATE OR REPLACE PROCEDURE get_num_results(query VARCHAR)
RETURNS INTEGER
LANGUAGE SQL
AS
DECLARE
row_count INTEGER DEFAULT 0;
stmt VARCHAR DEFAULT 'SELECT COUNT(*) FROM (' || query || ')';
res RESULTSET DEFAULT (EXECUTE IMMEDIATE :stmt);
cur CURSOR FOR res;
BEGIN
OPEN cur;
FETCH cur INTO row_count;
RETURN row_count;
END;
Observação: se você estiver usando o método SnowSQL, o Classic Console, execute_stream
ou execute_string
no código Python Connector, use este exemplo (consulte Uso do Script Snowflake em SnowSQL, Classic Console e conector Python):
CREATE OR REPLACE PROCEDURE get_num_results(query VARCHAR)
RETURNS INTEGER
LANGUAGE SQL
AS
$$
DECLARE
row_count INTEGER DEFAULT 0;
stmt VARCHAR DEFAULT 'SELECT COUNT(*) FROM (' || query || ')';
res RESULTSET DEFAULT (EXECUTE IMMEDIATE :stmt);
cur CURSOR FOR res;
BEGIN
OPEN cur;
FETCH cur INTO row_count;
RETURN row_count;
END;
$$
;
O exemplo a seguir chama o procedimento:
CALL get_num_results('SELECT 1');
+-----------------+
| GET_NUM_RESULTS |
|-----------------|
| 1 |
+-----------------+
O SQL dinâmico aceita variáveis de vinculação. O exemplo de Snowflake Scripting a seguir usa variáveis de vinculação representadas pelos espaços reservados ?
para construir instruções SQL dinamicamente no tempo de execução. Esse bloco seleciona dados da seguinte tabela invoices
:
CREATE OR REPLACE TABLE invoices (price NUMBER(12, 2));
INSERT INTO invoices (price) VALUES
(11.11),
(22.22);
Execute o bloco anônimo:
DECLARE
rs RESULTSET;
query VARCHAR DEFAULT 'SELECT * FROM invoices WHERE price > ? AND price < ?';
minimum_price NUMBER(12,2) DEFAULT 20.00;
maximum_price NUMBER(12,2) DEFAULT 30.00;
BEGIN
rs := (EXECUTE IMMEDIATE :query USING (minimum_price, maximum_price));
RETURN TABLE(rs);
END;
Observação: se você estiver usando o método SnowSQL, o Classic Console, execute_stream
ou execute_string
no código Python Connector, use este exemplo (consulte Uso do Script Snowflake em SnowSQL, Classic Console e conector Python):
EXECUTE IMMEDIATE $$
DECLARE
rs RESULTSET;
query VARCHAR DEFAULT 'SELECT * FROM invoices WHERE price > ? AND price < ?';
minimum_price NUMBER(12,2) DEFAULT 20.00;
maximum_price NUMBER(12,2) DEFAULT 30.00;
BEGIN
rs := (EXECUTE IMMEDIATE :query USING (minimum_price, maximum_price));
RETURN TABLE(rs);
END;
$$
;
+-------+
| PRICE |
|-------|
| 22.22 |
+-------+
Comparação das técnicas para construir SQL dinamicamente¶
A tabela a seguir descreve as vantagens e desvantagens das técnicas de construção dinâmica do SQL.
Técnica |
Vantagens |
Desvantagens |
---|---|---|
Função TO_QUERY |
|
|
SQL dinâmico |
|
|