사용자 정의 함수

사용자 정의 함수는 쿼리 자체(쿼리 정의 함수)의 일부로 정의되거나 데이터베이스 메타데이터(저장된 함수)의 일부로 저장될 수 있는 재사용 가능한 하위 쿼리입니다. 사용자 정의 함수는 이름을 통해 호출되고, 0개 이상의 입력 인수(스칼라 또는 테이블 형식)가 제공되며, 함수 본문에 따라 단일 값(스칼라 또는 테이블 형식)을 생성합니다.

사용자 정의 함수는 다음 두 가지 범주 중 하나에 속합니다.

  • 스칼라 함수
  • 테이블 형식 함수

함수의 입력 인수 및 출력에 따라 함수가 스칼라인지 아니면 테이블 형식인지가 결정되며, 함수 형식에 따라 함수 사용 방법이 설정됩니다.

단일 쿼리 내에서 사용자 정의 함수의 여러 사용을 최적화하려면 명명된 식을 사용하는 쿼리 최적화를 참조하세요.

스칼라 함수

  • 입력 인수가 없거나 모든 입력 인수가 스칼라 값
  • 단일 스칼라 값 생성
  • 스칼라 식이 허용되는 경우에 사용 가능
  • 정의된 행 컨텍스트만 사용할 수 있습니다.
  • 액세스 가능한 스키마에 있는 테이블(및 보기)만 참조 가능

테이블 형식 함수

  • 하나 이상의 테이블 형식 입력 인수와 0개 이상의 스칼라 입력 인수 허용
  • 그리고/또는 단일 테이블 형식 값 생성

함수 이름

유효한 사용자 정의 함수 이름은 다른 엔터티와 동일한 식별자 명명 규칙을 따라야 합니다.

또한 이름은 해당하는 정의 범위 내에서 고유해야 합니다.

참고

저장된 함수와 테이블의 이름이 같은 경우 해당 이름에 대한 참조는 테이블 이름이 아닌 저장된 함수로 처리됩니다. 대신 table 함수를 사용하여 테이블을 참조하십시오.

입력 인수

유효한 사용자 정의 함수는 다음 규칙을 따릅니다.

  • 사용자 정의 함수에는 입력 인수가 0개 이상인 강력한 형식의 목록이 있습니다.
  • 입력 인수에는 이름, 형식 및 기본값(스칼라 인수의 경우)이 포함되어 있습니다.
  • 입력 인수의 이름이 식별자입니다.
  • 입력 인수의 형식은 스칼라 데이터 형식 또는 테이블 형식 스키마 중 하나입니다.

구문적으로 입력 인수 목록은 쉼표로 구분된 인수 정의 목록이며 괄호로 묶여 있습니다. 각 인수 정의는 다음과 같이 지정됩니다.

ArgName:ArgType [= ArgDefaultValue]

테이블 형식 인수의 경우 ArgType 은 테이블 정의(괄호 및 열 이름/형식 쌍 목록)와 동일한 구문을 가지며, "모든 테이블 형식 스키마"를 나타내는 독방 (*) 이 추가됩니다.

다음은 그 예입니다.

Syntax 입력 인수 목록 설명
() 인수 없음
(s:string) string 형식의 값을 사용하는 단일 스칼라 인수 s
(a:long, b:bool=true) 두 개의 스칼라 인수. 두 번째 인수는 기본값이 있음
(T1:(*), T2(r:real), b:bool) 세 개의 인수(그 중 2개는 테이블 형식 인수이고 나머지 하나는 스칼라 인수)

참고

테이블 형식 입력 인수와 스칼라 입력 인수를 모두 사용하는 경우 모든 테이블 형식 입력 인수를 스칼라 입력 인수 앞에 배치하세요.

예제

스칼라 함수

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

인수가 없는 테이블 형식 함수

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

인수가 있는 테이블 형식 함수

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

출력

x
9
10

열을 지정하지 않고 테이블 형식 입력을 사용하는 테이블 형식 함수. 모든 테이블을 함수에 전달할 수 있으며, 함수 내에서 테이블 열을 참조할 수 없습니다.

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

출력

x
1
2
3

사용자 정의 함수 선언

사용자 정의 함수를 선언하여 다음을 제공합니다.

  • 함수 이름
  • 함수 스키마(허용되는 매개 변수. 있는 경우)
  • 함수 본문

참고

오버로드 함수는 지원되지 않습니다. 동일한 이름과 서로 다른 입력 스키마를 사용하여 여러 함수를 만들 수 없습니다.

람다 함수는 이름이 없으며 let 문을 사용하여 이름에 바인딩됩니다. 따라서 사용자 정의 저장 함수로 간주할 수 있습니다. 예제: 두 인수(s라는 stringi라는 long)를 허용하는 람다 함수에 대한 선언을 예로 들 수 있습니다. 이 함수는 첫 번째 인수(숫자로 변환한 후)와 두 번째 인수의 곱을 반환합니다. 람다는 이름 f에 바인딩됩니다.

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

함수 본문에는 다음이 포함됩니다.

  • 함수의 반환 값(스칼라 또는 테이블 형식 값)을 제공하는 정확히 하나의 식
  • 함수 본문의 범위에 해당하는 let 문의 수(0개 이상). 이 값을 지정하는 경우 let 문은 함수의 반환 값을 정의하는 식 앞에 와야 합니다.
  • 함수에서 사용하는 쿼리 매개 변수를 선언하는 쿼리 매개 변수 명령문의 수(0개 이상). 이 값을 지정하는 경우 이 명령문은 함수의 반환 값을 정의하는 식 앞에 와야 합니다.

참고

"최상위 수준" 쿼리에서 지원되는 다른 종류의 쿼리 명령문은 함수 본문 내에서 지원되지 않습니다. 두 문은 세미콜론으로 구분해야 합니다.

사용자 정의 함수 예제

다음 섹션에서는 사용자 정의 함수를 사용하는 방법의 예를 보여 줍니다.

let 문을 사용하는 사용자 정의 함수

다음 예제에서는 ID라는 매개 변수를 허용하는 사용자 정의 함수(람다)를 보여 줍니다. 함수는 Test라는 이름에 바인딩되며 Test3 정의에서 ID 매개 변수를 사용하는 세 개의 let 문을 사용합니다. 실행할 때 쿼리의 출력은 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

매개 변수의 기본값을 정의하는 사용자 정의 함수

다음 예제에서는 세 가지 인수를 허용하는 함수를 보여줍니다. 후자의 두 값은 기본값이며 호출 사이트에 있을 필요가 없습니다.

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"

사용자 정의 함수 호출

사용자 정의 함수를 호출하는 메서드는 함수가 수신해야 하는 인수에 따라 달라집니다. 다음 섹션에서는 인수 없이 UDF를 호출하고, 스칼라 인수를 사용하여 UDF를 호출하고, 테이블 형식 인수를 사용하여 UDF를 호출하는 방법을 설명합니다.

인수 없이 UDF 호출

인수를 사용하지 않고 이름이나 이름 및 빈 인수 목록을 괄호로 사용하여 호출할 수 있는 사용자 정의 함수입니다.

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

스칼라 인수를 사용하여 UDF 호출

하나 이상의 스칼라 인수를 사용하는 사용자 정의 함수는 함수 이름과 괄호 안에 구체적인 인수 목록을 사용하여 호출할 수 있습니다.

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

테이블 형식 인수를 사용하여 UDF 호출

하나 이상의 테이블 인수(스칼라 인수 수 포함)를 사용하고 함수 이름과 구체적인 인수 목록을 괄호로 사용하여 호출할 수 있는 사용자 정의 함수입니다.

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

invoke 연산자를 사용하여 하나 이상의 테이블 인수를 사용하고 테이블을 반환하는 사용자 정의 함수를 호출할 수도 있습니다. 이 함수는 함수에 대한 첫 번째 구체적인 테이블 인수가 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(":-)")

기본값

다음과 같은 조건에서는 함수가 일부 매개 변수의 기본값을 제공할 수도 있습니다.

  • 기본값은 스칼라 매개 변수에만 제공됩니다.
  • 기본값은 항상 리터럴(상수)입니다. 임의의 계산일 수 없습니다.
  • 기본값이 없는 매개 변수는 기본값이 있는 매개 변수보다 항상 우선합니다.
  • 호출자는 함수 선언과 동일한 순서로 정렬된 기본값이 없는 모든 매개 변수의 값을 제공해야 합니다.
  • 호출자는 기본값이 있는 매개 변수의 값을 제공할 필요가 없지만, 제공해도 됩니다.
  • 호출자는 매개 변수의 순서와 일치하지 않는 순서로 인수를 제공해도 됩니다. 이 경우 인수의 이름을 지정해야 합니다.

다음 예제에서는 두 개의 동일한 레코드가 있는 테이블을 반환합니다. f를 처음 호출할 때 인수는 완전히 "스크램블"되므로 각 인수의 이름이 명시적으로 지정됩니다.

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"

출력

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

함수 보기

인수를 사용하지 않고 테이블 형식 식을 반환하는 사용자 정의 함수는 보기로 표시할 수 있습니다. 사용자 정의 함수를 뷰로 표시하면 와일드카드 테이블 이름 확인이 수행될 때마다 함수가 테이블처럼 동작합니다.

다음 예제에서는 두 개의 사용자 정의 함수 T_viewT_notview를 보여주고, 첫 번째 함수만 union에서 와일드카드 참조로 확인되는 이유를 보여줍니다.

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

제한

다음 제한 사항이 적용됩니다.

  • 사용자 정의 함수는 함수가 호출되는 행 컨텍스트에 따라 달라지는 toscalar() 호출 정보를 전달할 수 없습니다.
  • 테이블 형식 식을 반환하는 사용자 정의 함수는 행 컨텍스트에 따라 달라지는 인수를 사용하여 호출할 수 없습니다.
  • 하나 이상의 테이블 형식 입력을 사용하는 함수는 원격 클러스터에서 호출할 수 없습니다.
  • 스칼라 함수는 원격 클러스터에서 호출할 수 없습니다.

사용자 정의 함수가 스칼라 함수로만 구성되고 toscalar()를 사용하지 않는 경우에만 행 컨텍스트에 따라 달라지는 인수를 사용하여 사용자 정의 함수를 호출할 수 있습니다.

예제

지원되는 스칼라 함수

테이블 형식 식을 참조하지 않는 스칼라 함수이므로 다음 쿼리가 지원 f 됩니다.

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)

테이블 형식 식을 Table1 참조하지만 현재 행 컨텍스트f(10)에 대한 참조 없이 호출되는 스칼라 함수이므로 다음 쿼리가 지원 f 됩니다.

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)

지원되지 않는 스칼라 함수

는 테이블 형식 식을 Table1참조하고 현재 행 컨텍스트f(Column)에 대한 참조로 호출되는 스칼라 함수이므로 다음 쿼리는 지원 f 되지 않습니다.

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)

지원되지 않는 테이블 형식 함수

스칼라 값이 필요한 컨텍스트에서 호출되는 테이블 형식 함수이므로 다음 쿼리는 지원 f 되지 않습니다.

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)

사용자 정의 함수에서 현재 지원되지 않는 기능

완전성을 위해 현재 지원되지 않는 사용자 정의 함수에 대해 일반적으로 요청되는 몇 가지 기능은 다음과 같습니다.

  1. 함수 오버로드: 현재 함수를 오버로드할 수 있는 방법이 없습니다(동일한 이름과 다른 입력 스키마를 사용하여 여러 함수를 만드는 방법).

  2. 기본값: 함수에 대한 스칼라 매개 변수의 기본값은 스칼라 리터럴(상수)이어야 합니다.