Fungsi yang ditentukan pengguna

Fungsi yang ditentukan pengguna adalah subkueri yang dapat digunakan kembali yang dapat didefinisikan sebagai bagian dari kueri itu sendiri (fungsi yang ditentukan kueri), atau disimpan sebagai bagian dari metadata database (fungsi tersimpan). Fungsi yang ditentukan pengguna dipanggil melalui nama, dilengkapi dengan argumen input nol atau lebih (yang dapat berupa skalar atau tabular), dan menghasilkan nilai tunggal (yang dapat berupa skalar atau tabular) berdasarkan isi fungsi.

Fungsi yang ditentukan pengguna termasuk dalam salah satu dari dua kategori:

  • Fungsi bernilai skalar
  • Fungsi bertabel

Argumen input dan output fungsi menentukan apakah itu skalar atau tabular, yang kemudian menetapkan cara hal itu dapat digunakan.

Untuk mengoptimalkan beberapa penggunaan fungsi yang ditentukan pengguna dalam kueri tunggal, lihat Mengoptimalkan kueri yang menggunakan ekspresi bernama.

Fungsi bernilai skalar

  • Memiliki argumen input nol, atau semua argumen inputnya adalah nilai skalar
  • Menghasilkan nilai skalar tunggal
  • Dapat digunakan di mana pun ekspresi skalar diizinkan
  • Hanya dapat menggunakan konteks baris tempat didefinisikan
  • Hanya dapat merujuk ke tabel (dan tampilan) yang berada dalam skema yang dapat diakses

Fungsi tabular

  • Menerima satu atau beberapa argumen input tabular, dan argumen input skalar nol atau lebih, dan/atau:
  • Menghasilkan nilai tabular tunggal

Nama fungsi

Nama fungsi yang ditentukan pengguna yang valid harus mengikuti aturan penamaan pengidentifikasi yang sama dengan entitas lain.

Nama juga harus unik dalam cakupan definisinya.

Catatan

Jika fungsi tersimpan dan tabel keduanya memiliki nama yang sama, maka referensi apa pun ke nama tersebut akan diselesaikan ke fungsi tersimpan, bukan nama tabel. Gunakan fungsi tabel untuk mereferensikan tabel sebagai gantinya.

Argumen input

Fungsi yang ditentukan pengguna yang valid mengikuti aturan ini:

  • Fungsi yang ditentukan pengguna memiliki daftar argumen input nol atau lebih yang diketik dengan jelas.
  • Argumen input memiliki nama, jenis, dan (untuk argumen skalar) nilai default.
  • Nama argumen input adalah pengidentifikasi.
  • Jenis argumen input adalah salah satu jenis data skalar, atau skema tabular.

Secara sintaksis, daftar argumen input adalah daftar definisi argumen yang dipisahkan koma, diapit dalam tanda kurung. Setiap definisi argumen ditentukan sebagai

ArgName:ArgType [= ArgDefaultValue]

Untuk argumen tabular, ArgType memiliki sintaksis yang sama dengan definisi tabel (tanda kurung dan daftar nama kolom /pasangan jenis), dengan tambahan dari soliter (*) yang menunjukkan "skema tabular apa pun".

Contohnya:

Sintaks Memasukkan deskripsi daftar argumen
() Tidak ada argumen
(s:string) Argumen skalar tunggal disebut s yang mengambil nilai jenis string
(a:long, b:bool=true) Dua argumen skalar, yang kedua memiliki nilai default
(T1:(*), T2(r:real), b:bool) Tiga argumen (dua argumen tabular dan satu argumen skalar)

Catatan

Saat menggunakan argumen input tabular dan argumen input skalar, letakkan semua argumen input tabular sebelum argumen input skalar.

Contoh

Fungsi bernilai skalar

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()

Fungsi tabular tanpa argumen

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

Fungsi tabular dengan argumen

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

Output

x
9
10

Fungsi tabular yang menggunakan input tabular tanpa kolom yang ditentukan. Tabel apa pun dapat diteruskan ke fungsi, dan tidak ada kolom tabel yang dapat direferensikan di dalam fungsi.

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

Output

x
1
2
3

Mendeklarasikan fungsi yang ditentukan pengguna

Deklarasi fungsi yang ditentukan pengguna menyediakan:

  • Name fungsi
  • Skema fungsi (parameter yang diterimanya, jika ada)
  • Isi fungsi

Catatan

Fungsi yang kelebihan beban tidak didukung. Anda tidak dapat membuat beberapa fungsi dengan nama yang sama dan skema input yang berbeda.

Tip

Fungsi Lambda tidak memiliki nama dan terikat pada nama menggunakan pernyataan let. Oleh karena itu, mereka dapat dianggap sebagai fungsi tersimpan yang ditentukan pengguna. Contoh: Deklarasi untuk fungsi lambda yang menerima dua argumen (string dipanggil s dan long dipanggil i). Ini mengembalikan produk yang pertama (setelah mengonversinya menjadi angka) dan yang kedua. Lambda terikat pada nama f:

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

Isi fungsi meliputi:

  • Tepat satu ekspresi, yang memberikan nilai pengembalian fungsi (nilai skalar atau tabular).
  • Setiap angka (nol atau lebih) dari pernyataan let, yang cakupannya berasal dari isi fungsi. Jika ditentukan, pernyataan let harus mendahului ekspresi yang menentukan nilai pengembalian fungsi.
  • Setiap angka (nol atau lebih) dari pernyataan parameter kueri, yang mendeklarasikan parameter kueri yang digunakan oleh fungsi. Jika ditentukan, mereka harus mendahului ekspresi yang mendefinisikan nilai pengembalian fungsi.

Catatan

Jenis pernyataan kueri lain yang didukung pada kueri "tingkat atas" tidak didukung di dalam isi fungsi. Setiap dua pernyataan harus dipisahkan oleh titik koma.

Contoh fungsi yang ditentukan pengguna

Bagian berikut menunjukkan contoh cara menggunakan fungsi yang ditentukan pengguna.

Fungsi yang ditentukan pengguna yang menggunakan pernyataan let

Contoh berikut menunjukkan fungsi yang ditentukan pengguna (lambda) yang menerima parameter bernama ID. Fungsi terkait dengan nama Test dan menggunakan tiga pernyataan let, yang mana definisi Test3 menggunakan parameter ID. Saat dijalankan, output dari kueri adalah 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

Fungsi yang ditentukan pengguna yang menentukan nilai default untuk parameter

Contoh berikut menunjukkan fungsi yang menerima tiga argumen. Dua yang terakhir memiliki nilai default dan tidak harus ada di situs panggilan.

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"

Memanggil fungsi yang ditentukan pengguna

Metode untuk memanggil fungsi yang ditentukan pengguna tergantung pada argumen yang diharapkan fungsi untuk diterima. Bagian berikut mencakup cara memanggil UDF tanpa argumen, memanggil UDF dengan argumen skalar, dan memanggil UDF dengan argumen tabular.

Memanggil UDF tanpa argumen

Fungsi yang ditentukan pengguna yang tidak mengambil argumen dan dapat dipanggil baik dengan namanya, atau dengan namanya dan daftar argumen kosong dalam tanda kurung.

// 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())

Memanggil UDF dengan argumen skalar

Fungsi yang ditentukan pengguna yang mengambil satu atau beberapa argumen skalar dapat dipanggil dengan menggunakan nama fungsi dan daftar argumen konkret dalam tanda kurung:

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

Memanggil UDF dengan argumen tabular

Fungsi yang ditentukan pengguna yang mengambil satu atau beberapa argumen tabel (dengan sejumlah argumen skalar) dan dapat dipanggil menggunakan nama fungsi serta daftar argumen konkret dalam tanda kurung:

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

Anda juga dapat menggunakan operator invoke untuk memanggil fungsi yang ditentukan pengguna yang mengambil satu atau beberapa argumen tabel dan mengembalikan tabel. Fungsi ini berguna ketika argumen tabel konkret pertama untuk fungsi adalah sumber operator 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(":-)")

Nilai default

Fungsi dapat memberikan nilai default ke beberapa parameternya dalam kondisi berikut:

  • Nilai default hanya dapat disediakan untuk parameter skalar.
  • Nilai default selalu harfiah (konstanta). Mereka tidak bisa menjadi perhitungan arbitrer.
  • Parameter tanpa nilai default selalu mendahului parameter yang memiliki nilai default.
  • Pemanggil harus memberikan nilai semua parameter tanpa nilai default yang diatur dalam urutan yang sama dengan deklarasi fungsi.
  • Pemanggil tidak perlu memberikan nilai untuk parameter dengan nilai default, tetapi dapat melakukannya.
  • Pemanggil dapat memberikan argumen dalam urutan yang tidak sesuai dengan urutan parameter. Jika demikian, mereka harus menyebutkan argumen mereka.

Contoh berikut mengembalikan tabel dengan dua rekaman identik. Dalam invokasi f pertama, argumen benar-benar "diacak", sehingga masing-masing secara eksplisit diberi nama:

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"

Output

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

Menampilkan fungsi

Fungsi yang ditentukan pengguna yang tidak mengambil argumen dan mengembalikan ekspresi tabular dapat ditandai sebagai tampilan. Menandai fungsi yang ditentukan pengguna sebagai tampilan berarti bahwa fungsi berperilaku seperti tabel setiap kali resolusi nama tabel wildcard dilakukan.

Contoh berikut menunjukkan dua fungsi yang ditentukan pengguna, T_view dan T_notview, dan menunjukkan bagaimana hanya yang pertama yang diselesaikan dengan referensi kartubebas di union:

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

Batasan

Pembatasan berikut berlaku:

  • Fungsi yang ditentukan pengguna tidak dapat diteruskan ke informasi invokasi toscalar() yang bergantung pada konteks baris tempat fungsi dipanggil.
  • Fungsi yang ditentukan pengguna yang mengembalikan ekspresi tabular tidak dapat dipanggil dengan argumen yang bervariasi dengan konteks baris.
  • Fungsi yang mengambil setidaknya satu input tabular tidak dapat dipanggil pada kluster jarak jauh.
  • Fungsi bernilai skalar tidak dapat dipanggil pada kluster jarak jauh.

Satu-satunya tempat fungsi yang ditentukan pengguna dapat dipanggil dengan argumen yang bervariasi dengan konteks baris adalah ketika fungsi yang ditentukan pengguna hanya terdiri dari fungsi skalar dan tidak menggunakan toscalar().

Contoh

Fungsi skalar yang didukung

Kueri berikut ini didukung karena f merupakan fungsi skalar yang tidak mereferensikan ekspresi tabular apa pun.

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)

Kueri berikut ini didukung karena f merupakan fungsi skalar yang mereferensikan ekspresi Table1 tabular tetapi dipanggil tanpa referensi ke konteks f(10)baris saat ini :

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)

Fungsi skalar yang tidak didukung

Kueri berikut ini tidak didukung karena f merupakan fungsi skalar yang mereferensikan ekspresi Table1tabular , dan dipanggil dengan referensi ke konteks f(Column)baris saat ini :

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)

Fungsi tabular yang tidak didukung

Kueri berikut ini tidak didukung karena f merupakan fungsi tabular yang dipanggil dalam konteks yang mengharapkan nilai skalar.

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)

Fitur yang saat ini tidak didukung oleh fungsi yang ditentukan pengguna

Untuk kelengkapan, berikut adalah beberapa fitur yang umum diminta untuk fungsi yang ditentukan pengguna yang saat ini tidak didukung:

  1. Fungsi yang kelebihan beban: Saat ini tidak ada cara untuk membebani fungsi (cara untuk membuat beberapa fungsi dengan nama yang sama dan skema input yang berbeda).

  2. Nilai default: Nilai default untuk parameter skalar ke fungsi harus berupa harfiah skalar (konstanta).