Problembehandlung bei SQL-UDFs

Unter diesem Thema finden Sie Informationen zur Problembehandlung für SQL-UDFs (benutzerdefinierte Funktionen).

Unter diesem Thema:

Problembehandlung

Tipps

Wenn Sie eine SQL-UDF in einer Maskierungsrichtlinie verwenden, stellen Sie sicher, dass die Datentypen von UDF-Spalte und Maskierungsrichtlinie übereinstimmen.

Fehlermeldung: Unsupported subquery type

Ursache:

Wenn eine UDF einen Abfrageausdruck enthält, kann die UDF als Unterabfrage fungieren. Wenn einer Unterabfrage ein Spaltenname übergeben wird, kann die Unterabfrage als korrelierte Unterabfrage fungieren. Wenn eine korrelierte Unterabfrage gegen die Snowflake-Regeln für korrelierte Unterabfragen verstößt, erhält der Benutzer die Fehlermeldung Unsupported subquery type. Das folgende Beispiel zeigt eine ungültige korrelierte Unterabfrage und wie sich eine UDF ähnlich wie eine ungültige korrelierte Unterabfrage verhalten kann.

Erstellen Sie ein Tabellenpaar, und laden Sie Daten in diese Tabellen:

CREATE TABLE stores (store_ID INTEGER, city VARCHAR);
CREATE TABLE employee_sales (employee_ID INTEGER, store_ID INTEGER, sales NUMERIC(10,2), 
    sales_date DATE);
INSERT INTO stores (store_ID, city) VALUES 
    (1, 'Winnipeg'),
    (2, 'Toronto');
INSERT INTO employee_sales (employee_ID, store_ID, sales, sales_date) VALUES 
    (1001, 1, 9000.00, '2020-01-27'),
    (1002, 1, 2000.00, '2020-01-27'),
    (2001, 2, 6000.00, '2020-01-27'),
    (2002, 2, 4000.00, '2020-01-27'),
    (2002, 2, 5000.00, '2020-01-28')
    ;
Copy

Die folgende SQL-Anweisung enthält eine korrelierte Unterabfrage, die nicht den Snowflake-Regeln entspricht. Dieser Code verursacht einen Unsupported subquery type-Fehler:

SELECT employee_ID,
       store_ID,
       (SELECT city FROM stores WHERE stores.store_ID = employee_sales.store_ID)
    FROM employee_sales;
Copy

Mit dem folgenden Code wird eine Unterabfrage-ähnliche UDF erstellt und dann so aufgerufen, dass eine korrelierte Unterabfrage ähnlich der oben gezeigten erstellt wird:

CREATE FUNCTION subquery_like_udf(X INT)
    RETURNS VARCHAR
    LANGUAGE SQL
    AS
    $$
        SELECT city FROM stores WHERE stores.store_ID = X
    $$;
Copy
SELECT employee_ID, subquery_like_udf(employee_sales.store_ID)
    FROM employee_sales;
Copy
Lösung 1:

Wenn die UDF einen Abfrageausdruck enthält, rufen Sie die UDF nur auf eine Weise auf, die den Regeln für Unterabfragen entspricht.

In der folgenden Anweisung wird die UDF beispielsweise mit einer Konstante und nicht mit einem Spaltennamen aufgerufen, sodass die UDF nicht wie eine korrelierte Unterabfrage fungiert:

SELECT subquery_like_udf(1);
+----------------------+
| SUBQUERY_LIKE_UDF(1) |
|----------------------|
| Winnipeg             |
+----------------------+
Copy
Lösung 2:

In einigen Fällen können Sie die UDF neu schreiben, um dasselbe Ziel auf andere Weise zu erreichen. Eine korrelierte Unterabfrage ist zulässig, wenn die Unterabfrage statisch so festgelegt werden kann, dass sie eine Zeile zurückgibt. Die folgende UDF verwendet eine Aggregatfunktion und gibt daher nur eine Zeile zurück:

CREATE FUNCTION subquery_like_udf_2(X INT)
    RETURNS VARCHAR
    LANGUAGE SQL
    AS
    $$
        SELECT ANY_VALUE(city) FROM stores WHERE stores.store_ID = X
    $$;
Copy
SELECT employee_ID, sales_date, subquery_like_udf_2(employee_sales.store_ID)
    FROM employee_sales
    ORDER BY employee_ID, sales_date;
+-------------+------------+----------------------------------------------+
| EMPLOYEE_ID | SALES_DATE | SUBQUERY_LIKE_UDF_2(EMPLOYEE_SALES.STORE_ID) |
|-------------+------------+----------------------------------------------|
|        1001 | 2020-01-27 | Winnipeg                                     |
|        1002 | 2020-01-27 | Winnipeg                                     |
|        2001 | 2020-01-27 | Toronto                                      |
|        2002 | 2020-01-27 | Toronto                                      |
|        2002 | 2020-01-28 | Toronto                                      |
+-------------+------------+----------------------------------------------+
Copy