Uživatelem definované funkce

Uživatelem definované funkce jsou opakovaně použitelné poddotazy, které lze definovat jako součást samotného dotazu (funkce definované dotazem) nebo uložit jako součást metadat databáze (uložené funkce). Uživatelem definované funkce se vyvolávají prostřednictvím názvu, poskytují se nula nebo více vstupních argumentů (které můžou být skalární nebo tabulkové) a vytvářejí jednu hodnotu (která může být skalární nebo tabulková) na základě textu funkce.

Uživatelem definovaná funkce patří do jedné ze dvou kategorií:

  • Skalární funkce
  • Tabulkové funkce

Vstupní argumenty a výstup funkce určují, zda je funkce skalární, nebo tabulková, což následně určuje způsob jejího použití.

Pokud chcete optimalizovat více použití uživatelem definovaných funkcí v rámci jednoho dotazu, přečtěte si téma Optimalizace dotazů, které používají pojmenované výrazy.

Skalární funkce

  • Má nula vstupních argumentů nebo všechny jeho vstupní argumenty jsou skalární hodnoty.
  • Vytvoří jednu skalární hodnotu.
  • Lze použít všude, kde je skalární výraz povolený.
  • Může použít pouze kontext řádku, ve kterém je definován.
  • Může odkazovat pouze na tabulky (a zobrazení), které jsou v přístupném schématu.

Tabulková funkce

  • Přijímá jeden nebo více tabulkových vstupních argumentů a nula nebo více skalárních vstupních argumentů a/nebo:
  • Vytvoří jednu tabulkovou hodnotu.

Názvy funkcí

Platné uživatelem definované názvy funkcí musí dodržovat stejná pravidla pojmenování identifikátorů jako jiné entity.

Název musí být také jedinečný ve svém oboru definice.

Poznámka

Pokud uložená funkce i tabulka mají stejný název, přeloží se všechny odkazy na tento název na uloženou funkci, nikoli na název tabulky. Místo toho použijte funkci table k odkazu na tabulku.

Vstupní argumenty

Platné uživatelem definované funkce se řídí těmito pravidly:

  • Uživatelsky definovaná funkce má seznam se silnými typy nula nebo více vstupních argumentů.
  • Vstupní argument má název, typ a (pro skalární argumenty) výchozí hodnotu.
  • Název vstupního argumentu je identifikátor.
  • Typ vstupního argumentu je buď jeden ze skalárních datových typů, nebo tabulkové schéma.

Seznam vstupních argumentů je syntakticky čárkami oddělený seznam definic argumentů zabalený v závorkách. Každá definice argumentu je určena jako

ArgName:ArgType [= ArgDefaultValue]

U tabulkových argumentů má ArgType stejnou syntaxi jako definice tabulky (závorky a seznam párů název/typ sloupce) s přidáním solitéry (*) označující "libovolné tabulkové schéma".

Příklad:

Syntax Popis seznamu vstupních argumentů
() Žádné argumenty
(s:string) Jeden skalární argument s názvem s převzetí hodnoty typu string
(a:long, b:bool=true) Dva skalární argumenty, z nichž druhý má výchozí hodnotu
(T1:(*), T2(r:real), b:bool) Tři argumenty (dva tabulkové argumenty a jeden skalární argument)

Poznámka

Při použití tabulkových vstupních argumentů i skalárních vstupních argumentů umístěte všechny vstupní argumenty tabulkového vstupu před skalární vstupní argumenty.

Příklady

Skalární funkce

let Add7 = (arg0:long = 5) { arg0 + 7 };
range x from 1 to 10 step 1
| extend x_plus_7 = Add7(x), five_plus_seven = Add7()

Tabulková funkce bez argumentů

let tenNumbers = () { range x from 1 to 10 step 1};
tenNumbers
| extend x_plus_7 = x + 7

Tabulková funkce s argumenty

let MyFilter = (T:(x:long), v:long) {
  T | where x >= v
};
MyFilter((range x from 1 to 10 step 1), 9)

Výstup

x
9
10

Tabulková funkce, která používá tabulkový vstup bez zadaného sloupce. Funkci lze předat libovolnou tabulku a ve funkci nelze odkazovat na žádné sloupce tabulky.

let MyDistinct = (T:(*)) {
  T | distinct *
};
MyDistinct((range x from 1 to 3 step 1))

Výstup

x
1
2
3

Deklarace uživatelem definovaných funkcí

Deklarace uživatelem definované funkce poskytuje:

  • Název funkce
  • Schéma funkce (parametry, které přijímá, pokud existují)
  • Text funkce

Poznámka

Přetížení funkcí není podporováno. Nemůžete vytvořit více funkcí se stejným názvem a různými vstupními schématy.

Tip

Funkce lambda nemají název a jsou vázané na název pomocí příkazu let. Proto je lze považovat za uživatelem definované uložené funkce. Příklad: Deklarace funkce lambda, která přijímá dva argumenty (volaný strings a volaný longi). Vrátí součin prvního (po převedení na číslo) a druhého. Lambda je vázána na název f:

let f=(s:string, i:long) {
    tolong(s) * i
};

Tělo funkce obsahuje :

  • Přesně jeden výraz, který poskytuje návratovou hodnotu funkce (skalární nebo tabulkovou hodnotu).
  • Libovolné číslo (nula nebo více) příkazů let, jejichž obor je oborem tělo funkce. Pokud je zadaný, musí příkazy let předcházet výrazu definujícímu návratovou hodnotu funkce.
  • Libovolný počet příkazů parametrů dotazu (nula nebo více), které deklarují parametry dotazu používané funkcí. Pokud jsou zadané, musí předcházet výrazu definujícímu návratovou hodnotu funkce.

Poznámka

Jiné typy příkazů dotazu, které jsou podporovány v dotazu na nejvyšší úrovni, nejsou podporovány v těle funkce. Všechny dva příkazy musí být odděleny středníkem.

Příklady uživatelem definovaných funkcí

Následující část ukazuje příklady použití uživatelem definovaných funkcí.

Uživatelem definovaná funkce, která používá příkaz let

Následující příklad ukazuje uživatelem definovanou funkci (lambda), která přijímá parametr s názvem ID. Funkce je svázaná s názvem Test a používá tři příkazy let , ve kterých definice Test3 používá parametr ID . Při spuštění je výstup dotazu 70:

let Test = (id: int) {
  let Test2 = 10;
  let Test3 = 10 + Test2 + id;
  let Test4 = (arg: int) {
      let Test5 = 20;
      Test2 + Test3 + Test5 + arg
  };
  Test4(10)
};
range x from 1 to Test(10) step 1
| count

Uživatelem definovaná funkce, která definuje výchozí hodnotu parametru

Následující příklad ukazuje funkci, která přijímá tři argumenty. Poslední dvě mají výchozí hodnotu a nemusí být přítomny na webu volání.

let f = (a:long, b:string = "b.default", c:long = 0) {
  strcat(a, "-", b, "-", c)
};
print f(12, c=7) // Returns "12-b.default-7"

Vyvolání uživatelem definované funkce

Metoda vyvolání uživatelem definované funkce závisí na argumentech, které funkce očekává, že obdrží. V následujících částech se dozvíte, jak vyvolat UDF bez argumentů, jak vyvolat UDF se skalárními argumenty a jak vyvolat UDF s tabulkovými argumenty.

Vyvolání UDF bez argumentů

Uživatelem definovaná funkce, která nepřijímá žádné argumenty a může být vyvolána buď svým názvem, nebo názvem a prázdným seznamem argumentů v závorkách.

// Bind the identifier a to a user-defined function (lambda) that takes
// no arguments and returns a constant of type long:
let a=(){123};
// Invoke the function in two equivalent ways:
range x from 1 to 10 step 1
| extend y = x * a, z = x * a()
// Bind the identifier T to a user-defined function (lambda) that takes
// no arguments and returns a random two-by-two table:
let T=(){
  range x from 1 to 2 step 1
  | project x1 = rand(), x2 = rand()
};
// Invoke the function in two equivalent ways:
// (Note that the second invocation must be itself wrapped in
// an additional set of parentheses, as the union operator
// differentiates between "plain" names and expressions)
union T, (T())

Vyvolání UDF se skalárními argumenty

Uživatelem definovanou funkci, která přebírá jeden nebo více skalárních argumentů, lze vyvolat pomocí názvu funkce a konkrétního seznamu argumentů v závorkách:

let f=(a:string, b:string) {
  strcat(a, " (la la la)", b)
};
print f("hello", "world")

Vyvolání UDF s tabulkovými argumenty

Uživatelem definovaná funkce, která přijímá jeden nebo více argumentů tabulky (s libovolným počtem skalárních argumentů) a lze ji vyvolat pomocí názvu funkce a konkrétního seznamu argumentů v závorkách:

let MyFilter = (T:(x:long), v:long) {
  T | where x >= v
};
MyFilter((range x from 1 to 10 step 1), 9)

Operátor můžete použít invoke také k vyvolání uživatelem definované funkce, která přebírá jeden nebo více argumentů tabulky a vrací tabulku. Tato funkce je užitečná, pokud první konkrétní argument tabulky pro funkci je zdrojem operátoru invoke :

let append_to_column_a=(T:(a:string), what:string) {
    T | extend a=strcat(a, " ", what)
};
datatable (a:string) ["sad", "really", "sad"]
| invoke append_to_column_a(":-)")

Výchozí hodnoty

Funkce můžou u některých svých parametrů poskytovat výchozí hodnoty za následujících podmínek:

  • Výchozí hodnoty lze zadat pouze pro skalární parametry.
  • Výchozí hodnoty jsou vždy literály (konstanty). Nemohou to být libovolné výpočty.
  • Parametry bez výchozí hodnoty vždy předcházejí parametry, které mají výchozí hodnotu.
  • Volající musí zadat hodnotu všech parametrů bez výchozích hodnot uspořádaných ve stejném pořadí jako deklarace funkce.
  • Volající nemusí zadávat hodnotu parametrů s výchozími hodnotami, ale můžou to udělat.
  • Volající můžou zadávat argumenty v pořadí, které neodpovídá pořadí parametrů. Pokud ano, musí pojmenovat své argumenty.

Následující příklad vrátí tabulku se dvěma identickými záznamy. Při prvním vyvolání fjsou argumenty zcela "scrambled", takže každý z nich je explicitně pojmenován:

let f = (a:long, b:string = "b.default", c:long = 0) {
  strcat(a, "-", b, "-", c)
};
union
  (print x=f(c=7, a=12)), // "12-b.default-7"
  (print x=f(12, c=7))    // "12-b.default-7"

Výstup

x
12-b.default-7
12-b.default-7

Zobrazit funkce

Uživatelem definovanou funkci, která nepřijímá žádné argumenty a vrací tabulkový výraz, může být označena jako zobrazení. Označení uživatelem definované funkce jako zobrazení znamená, že se funkce chová jako tabulka při každém provedení překladu názvů tabulek se zástupnými znaky.

Následující příklad ukazuje dvě uživatelem definované funkce a T_notviewa ukazuje, T_view jak se pomocí odkazu se zástupným znakem v union:

let T_view = view () { print x=1 };
let T_notview = () { print x=2 };
union T*

Omezení

Vstupy mají nesledující mezení:

  • Uživatelem definované funkce nemohou předávat do informací o vyvolání toscalar(), které závisí na kontextu řádku, ve kterém je funkce volána.
  • Uživatelem definované funkce, které vracejí tabulkový výraz, nelze vyvolat s argumentem, který se liší podle kontextu řádku.
  • Funkci, která přijímá alespoň jeden tabulkový vstup, nelze ve vzdáleném clusteru vyvolat.
  • Skalární funkci nelze vyvolat ve vzdáleném clusteru.

Jediným místem, kde lze vyvolat uživatelem definovanou funkci s argumentem, který se liší podle kontextu řádku, je, když se uživatelem definovaná funkce skládá pouze ze skalárních funkcí a nepoužívá toscalar().

Příklady

Podporovaná skalární funkce

Následující dotaz je podporovaný, protože f se jedná o skalární funkci, která neodkazuje na žádný tabulkový výraz.

let Table1 = datatable(xdate:datetime)[datetime(1970-01-01)];
let Table2 = datatable(Column:long)[1235];
let f = (hours:long) { now() + hours*1h };
Table2 | where Column != 123 | project d = f(10)

Následující dotaz je podporovaný, protože f je skalární funkce, která odkazuje na tabulkový výraz Table1 , ale je vyvolána bez odkazu na kontext f(10)aktuálního řádku:

let Table1 = datatable(xdate:datetime)[datetime(1970-01-01)];
let Table2 = datatable(Column:long)[1235];
let f = (hours:long) { toscalar(Table1 | summarize min(xdate) - hours*1h) };
Table2 | where Column != 123 | project d = f(10)

Nepodporovaná skalární funkce

Následující dotaz není podporovaný, protože f se jedná o skalární funkci, která odkazuje na tabulkový výraz Table1a je vyvolána s odkazem na aktuální kontext f(Column)řádku:

let Table1 = datatable(xdate:datetime)[datetime(1970-01-01)];
let Table2 = datatable(Column:long)[1235];
let f = (hours:long) { toscalar(Table1 | summarize min(xdate) - hours*1h) };
Table2 | where Column != 123 | project d = f(Column)

Nepodporovaná tabulková funkce

Následující dotaz se nepodporuje, protože f se jedná o tabulkovou funkci, která je vyvolána v kontextu, který očekává skalární hodnotu.

let Table1 = datatable(xdate:datetime)[datetime(1970-01-01)];
let Table2 = datatable(Column:long)[1235];
let f = (hours:long) { range x from 1 to hours step 1 | summarize make_list(x) };
Table2 | where Column != 123 | project d = f(Column)

Funkce, které nejsou aktuálně podporovány uživatelem definovanými funkcemi

Pro úplnost uvádíme některé běžně požadované funkce pro uživatelem definované funkce, které se v současné době nepodporují:

  1. Přetížení funkce: V současné době neexistuje způsob, jak funkci přetížit (způsob, jak vytvořit více funkcí se stejným názvem a jiným vstupním schématem).

  2. Výchozí hodnoty: Výchozí hodnota skalárního parametru funkce musí být skalární literál (konstanta).