CREATE FUNCTION (SQL وPython)

ينطبق على:وضع علامة Databricks SQL وضع علامة Databricks Runtime

إنشاء دالة عددية أو جدول SQL تأخذ مجموعة من الوسيطات وترجع قيمة عددية أو مجموعة من الصفوف.

ينطبق على:وضع علامة Databricks SQL وضع علامة Databricks Runtime 13.3 LTS وما فوق

إنشاء دالة عددية Python تأخذ مجموعة من الوسيطات وترجع قيمة عددية.

تتطلب Python UDFs كتالوج Unity على مستودعات SQL بلا خادم أو pro، أو مجموعة كتالوج Unity لمستخدم مشترك أو واحد.

ينطبق على:وضع علامة Databricks SQL وضع علامة Databricks Runtime 14.1 وما فوق

بالإضافة إلى استدعاء المعلمة الموضعية، يمكنك أيضا استدعاء SQL وPython UDF باستخدام استدعاء المعلمة المسماة.

بناء الجملة

CREATE [OR REPLACE] [TEMPORARY] FUNCTION [IF NOT EXISTS]
    function_name ( [ function_parameter [, ...] ] )
    { [ RETURNS data_type ] |
      RETURNS TABLE [ ( column_spec [, ...]) ] }
    [ characteristic [...] ]
    { AS dollar_quoted_string | RETURN { expression | query } }

function_parameter
    parameter_name data_type [DEFAULT default_expression] [COMMENT parameter_comment]

column_spec
    column_name data_type [COMMENT column_comment]

characteristic
  { LANGUAGE { SQL | PYTHON } |
    [NOT] DETERMINISTIC |
    COMMENT function_comment |
    [CONTAINS SQL | READS SQL DATA] }

المعلمات

  • أو استبدال

    إذا تم تحديدها، يتم استبدال الدالة بنفس الاسم والتوقيع (عدد المعلمات وأنواع المعلمات). لا يمكنك استبدال دالة موجودة بتوقيع مختلف. هذا مفيد بشكل رئيسي لتحديث نص الدالة ونوع الإرجاع للدالة. لا يمكنك تحديد هذه المعلمة باستخدام IF NOT EXISTS.

  • المؤقته

    نطاق الدالة التي يتم إنشاؤها. عند تحديد TEMPORARY، تكون الدالة التي تم إنشاؤها صالحة ومرئية في جلسة العمل الحالية. لم يتم إدخال مستمر في الكتالوج.

  • إذا لم يكن موجودا

    إذا تم تحديدها، يتم إنشاء الدالة فقط عندما لا تكون موجودة. ينجح إنشاء الدالة (لا يتم طرح أي خطأ) إذا كانت الدالة المحددة موجودة بالفعل في النظام. لا يمكنك تحديد هذه المعلمة باستخدام OR REPLACE.

  • function_name

    اسم للدالة. بالنسبة إلى دالة دائمة، يمكنك اختياريا تأهيل اسم الدالة باسم مخطط. إذا لم يكن الاسم مؤهلا، يتم إنشاء الدالة الدائمة في المخطط الحالي.

  • function_parameter

    تحديد معلمة للدالة.

    • parameter_name

      يجب أن يكون اسم المعلمة فريدا داخل الدالة .

    • data_type

      أي نوع بيانات معتمد. بالنسبة إلى Python، data_type يتم تحويلها إلى نوع بيانات Python وفقا لتعيين اللغة هذا.

    • default_expression الافتراضي

      ينطبق على:وضع علامة Databricks SQL وضع علامة Databricks Runtime 10.4 LTS وما فوق

      افتراضي اختياري لاستخدامه عندما لا يقوم استدعاء دالة بتعيين وسيطة للمعلمة . default_expression يجب أن يكون قابلا للصب إلى data_type. يجب ألا يشير التعبير إلى معلمة أخرى أو يحتوي على استعلام فرعي.

      عند تحديد افتراضي لمعلمة واحدة، يجب أن تحتوي جميع المعلمات التالية أيضا على افتراضي.

      DEFAULT معتمد فقط LANGUAGE SQL .

    • تعليق التعليق

      وصف اختياري للمعلمة. comment يجب أن تكون قيمة حرفية STRING .

  • إرجاع data_type

    نوع بيانات الإرجاع للدالة العددية. بالنسبة إلى Python UDFs، يجب أن تتطابق القيم المرجعة تماما مع نوع البيانات كما هو محدد في data_type. وإلا، لمنع تحويلات النوع غير المتوقعة، ستفشل الدالة.

    بالنسبة إلى SQL UDF، هذه العبارة اختيارية. سيتم اشتقاق نوع البيانات من نص الدالة إذا لم يتم توفيره.

  • إرجاع الجدول [ (column_spec [,...] ) ]

    تحدد هذه العبارة الدالة كدالة جدول. اختياريا فإنه يحدد أيضا توقيع نتيجة دالة الجدول. إذا لم يتم تحديد أي column_spec، فسيتم اشتقاقه من نص SQL UDF.

    RETURNS TABLE معتمد فقط LANGUAGE SQL .

    • column_name

      يجب أن يكون اسم العمود فريدا داخل التوقيع.

    • data_type

      أي نوع بيانات معتمد.

    • column_comment التعليق

      وصف اختياري للعمود. comment يجب أن تكون قيمة حرفية STRING .

  • RETURN { expression | query }

    نص الدالة. بالنسبة للدالة العددية، يمكن أن تكون إما استعلاما أو تعبيرا. بالنسبة لدالة جدول، يمكن أن تكون استعلاما فقط. لا يمكن أن يحتوي التعبير على:

    ضمن نص الدالة، يمكنك الرجوع إلى المعلمة باسمها غير المؤهل أو عن طريق تأهيل المعلمة باسم الدالة.

  • AS dollar_quoted_definition

    dollar_quoted_definition هي دالة body Python محاطة باثنين من المطابقة $[tag]$body$[tag]$. tag يمكن أن تكون سلسلة فارغة.

    أمثلة:

    $$
      return “Hello world”
    $$
    
    $py$
      return "Hello World"
    $py$
    
  • مميزه

    جميع العبارات المميزة اختيارية. يمكنك تحديد أي عدد منها بأي ترتيب، ولكن يمكنك تحديد كل عبارة مرة واحدة فقط.

    • LANGUAGE SQL أو LANGUAGE PYTHON

      لغة تنفيذ الدالة.

    • [NOT] القطعيه

      ما إذا كانت الدالة حتمية أم لا. الدالة محددة عندما تقوم بإرجاع نتيجة واحدة فقط لمجموعة معينة من الوسيطات. يمكنك وضع علامة على دالة على أنها DETERMINISTIC عندما لا يكون نصها والعكس صحيح. قد يكون سبب ذلك هو تشجيع أو تثبيط تحسينات الاستعلام مثل الطي المستمر أو التخزين المؤقت للاستعلام. إذا لم تحدد خيار ths، يتم اشتقاقه من نص الدالة.

    • function_comment التعليق

      تعليق للدالة. function_comment يجب أن تكون سلسلة حرفية.

    • يحتوي على بيانات SQL أو READS SQL

      ما إذا كانت الدالة تقرأ البيانات بشكل مباشر أو غير مباشر من جدول أو طريقة عرض. عندما تقرأ الدالة بيانات SQL، لا يمكنك تحديد CONTAINS SQL. إذا لم تحدد أي من العبارتين، يتم اشتقاق الخاصية من نص الدالة.

المكتبات المدعومة في Python UDFs

لاستخدام أي تبعيات، استخدم import <package> داخل نص الدالة. على سبيل المثال، راجع ما يلي:

CREATE FUNCTION […]
AS $$
   import json
   [... (rest of function definition)]
$$

تقتصر التبعيات على مكتبة Python القياسية والمكتبات التالية:

الحزمة إصدار
التبييض 4.0.0
تجزئة 4.0.0
charset-normalizer 2.0.4
defusedxml 0.7.1
googleapis-common-protos 1.56.4
grpcio 1.47.0
حالة grpcio 1.47.0
مسار jmespath 0.10.0
joblib 1.1.0
numpy 1.20.3
التغليف 21.3
pandas 1.3.4
باتسي 0.5.2
protobuf 4.21.5
pyarrow 7.0.0
pyparsing 3.0.9
python-dateutil 2.8.2
pytz 2021.3
scikit-learn 0.24.2"
شفرة 1.7.1"
أدوات الإعداد 65.2.0
ستة 1.16.0
threadpoolctl 3.1.0
ترميزات الويب 0.5.1
وكلاء المستخدم 2.2.0
التشفير 38.0.4

الأمثلة

إنشاء دالة عددية SQL واستخدامها

> CREATE VIEW t(c1, c2) AS VALUES (0, 1), (1, 2);
-- Create a temporary function with no parameter.
> CREATE TEMPORARY FUNCTION hello() RETURNS STRING RETURN 'Hello World!';

> SELECT hello();
  Hello World!

-- Create a permanent function with parameters.
> CREATE FUNCTION area(x DOUBLE, y DOUBLE) RETURNS DOUBLE RETURN x * y;

-- Use a SQL function in the SELECT clause of a query.
> SELECT area(c1, c2) AS area FROM t;
 0.0
 2.0

-- Use a SQL function in the WHERE clause of a query.
> SELECT * FROM t WHERE area(c1, c2) > 0;
 1  2

-- Compose SQL functions.
> CREATE FUNCTION square(x DOUBLE) RETURNS DOUBLE RETURN area(x, x);

> SELECT c1, square(c1) AS square FROM t;
  0  0.0
  1  1.0

-- Create a non-deterministic function
> CREATE FUNCTION roll_dice()
    RETURNS INT
    NOT DETERMINISTIC
    CONTAINS SQL
    COMMENT 'Roll a single 6 sided die'
    RETURN (rand() * 6)::INT + 1;
-- Roll a single 6-sided die
> SELECT roll_dice();
 3

إنشاء واستخدام دالة تستخدم DEFAULTs

-- Extend the function to support variable number of sides and dice.
-- Use defaults to support a variable number of arguments
> DROP FUNCTION roll_dice;
> CREATE FUNCTION roll_dice(num_dice  INT DEFAULT 1 COMMENT 'number of dice to roll (Default: 1)',
                            num_sides INT DEFAULT 6 COMMENT 'number of sides per die (Default: 6)')
    RETURNS INT
    NOT DETERMINISTIC
    CONTAINS SQL
    COMMENT 'Roll a number of n-sided dice'
    RETURN aggregate(sequence(1, roll_dice.num_dice, 1),
                     0,
                     (acc, x) -> (rand() * roll_dice.num_sides)::int,
                     acc -> acc + roll_dice.num_dice);

-- Roll a single 6-sided die still works
> SELECT roll_dice();
 3

-- Roll 3 6-sided dice
> SELECT roll_dice(3);
 15

-- Roll 3 10-sided dice
> SELECT roll_dice(3, 10)
 21

-- Roll 3 10-sided dice using named parameter invocation
> SELECT roll_dice(10 => num_sides, num_dice => 3)
 17

-- Create a SQL function with a scalar subquery.
> CREATE VIEW scores(player, score) AS VALUES (0, 1), (0, 2), (1, 2), (1, 5);

> CREATE FUNCTION avg_score(p INT) RETURNS FLOAT
    COMMENT 'get an average score of the player'
    RETURN SELECT AVG(score) FROM scores WHERE player = p;

> SELECT c1, avg_score(c1) FROM t;
 0  1.5
 1  3.5

إنشاء دالة جدول SQL

-- Produce all weekdays between two dates
> CREATE FUNCTION weekdays(start DATE, end DATE)
    RETURNS TABLE(day_of_week STRING, day DATE)
    RETURN SELECT extract(DAYOFWEEK_ISO FROM day), day
             FROM (SELECT sequence(weekdays.start, weekdays.end)) AS T(days)
                  LATERAL VIEW explode(days) AS day
             WHERE extract(DAYOFWEEK_ISO FROM day) BETWEEN 1 AND 5;

-- Return all weekdays
> SELECT weekdays.day_of_week, day
    FROM weekdays(DATE'2022-01-01', DATE'2022-01-14');
  1     2022-01-03
  2     2022-01-04
  3     2022-01-05
  4     2022-01-06
  5     2022-01-07
  1     2022-01-10
  2     2022-01-11
  3     2022-01-12
  4     2022-01-13
  5     2022-01-14

-- Return weekdays for date ranges originating from a LATERAL correlation
> SELECT weekdays.*
    FROM VALUES (DATE'2020-01-01'),
                (DATE'2021-01-01'),
                (DATE'2022-01-01') AS starts(start),
         LATERAL weekdays(start, start + INTERVAL '7' DAYS);
  3     2020-01-01
  4     2020-01-02
  5     2020-01-03
  1     2020-01-06
  2     2020-01-07
  3     2020-01-08
  5     2021-01-01
  1     2021-01-04
  2     2021-01-05
  3     2021-01-06
  4     2021-01-07
  5     2021-01-08
  1     2022-01-03
  2     2022-01-04
  3     2022-01-05
  4     2022-01-06
  5     2022-01-07

استبدال دالة SQL

-- Replace a SQL scalar function.
> CREATE OR REPLACE FUNCTION square(x DOUBLE) RETURNS DOUBLE RETURN x * x;

-- Replace a SQL table function.
> CREATE OR REPLACE FUNCTION getemps(deptno INT)
    RETURNS TABLE (name STRING)
    RETURN SELECT name FROM employee e WHERE e.deptno = getemps.deptno;

-- Describe a SQL table function.
> DESCRIBE FUNCTION getemps;
 Function: default.getemps
 Type:     TABLE
 Input:    deptno INT
 Returns:  id   INT
           name STRING

إشعار

لا يمكنك استبدال دالة موجودة بتوقيع مختلف.

وصف دالة SQL

> DESCRIBE FUNCTION hello;
 Function: hello
 Type:     SCALAR
 Input:    ()
 Returns:  STRING

> DESCRIBE FUNCTION area;
 Function: default.area
 Type:     SCALAR
 Input:    x DOUBLE
           y DOUBLE
 Returns:  DOUBLE

> DESCRIBE FUNCTION roll_dice;
 Function: default.roll_dice
 Type:     SCALAR
 Input:    num_dice  INT
           num_sides INT
 Returns:  INT

> DESCRIBE FUNCTION EXTENDED roll_dice;
 Function:      default.roll_dice
 Type:          SCALAR
 Input:         num_dice  INT DEFAULT 1 'number of dice to roll (Default: 1)'
                num_sides INT DEFAULT 6 'number of sides per dice (Default: 6)'
 Returns:       INT
 Comment:       Roll a number of m-sided dice
 Deterministic: false
 Data Access:   CONTAINS SQL
 Configs:       ...
 Owner:         the.house@always.wins
 Create Time:   Sat Feb 12 09:29:02 PST 2022
 Body:          aggregate(sequence(1, roll_dice.num_dice, 1),
                      0,
                      (acc, x) -> (rand() * roll_dice.num_sides)::int,
                      acc -> acc + roll_dice.num_dice)

إنشاء وظائف Python

—- Hello World-like functionality using Python UDFs
> CREATE FUNCTION main.default.greet(s STRING)
  RETURNS STRING
  LANGUAGE PYTHON
  AS $$
    def greet(name):
      return "Hello " + name + "!"

    return greet(s) if s else None
  $$

—- Can import functions from std library and environment
> CREATE FUNCTION main.default.isleapyear(year INT)
  RETURNS BOOLEAN
  LANGUAGE PYTHON
  AS $$
    import calendar
    return calendar.isleap(year) if year else None
  $$

—- Must return the correct type. Otherwise will fail at runtime.
> CREATE FUNCTION main.default.a_number()
  RETURNS INTEGER
  LANGUAGE PYTHON
  AS $$
    # does not work: return "10"
    # does not work: return 3.14
    return 10
  $$

—- Deal with exceptions.
> CREATE FUNCTION main.default.custom_divide(n1 INT, n2 INT)
  RETURNS FLOAT
  LANGUAGE PYTHON
  AS $$
    try:
      return n1/n2
    except ZeroDivisionException:
    # in case of 0, we can return NULL.
    return None
  $$