> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> 저장된 쿼리로부터 REST API 엔드포인트를 손쉽게 생성합니다

# Query API 엔드포인트 설정

export const Image = ({img, alt, size = "lg"}) => {
  const normalizedSize = ["sm", "md", "lg"].includes(size) ? size : "lg";
  return <div className={`ch-image-${normalizedSize}`}>
      <Frame>
        <img src={img} alt={alt} />
      </Frame>
    </div>;
};

**Query API 엔드포인트** 기능을 사용하면 ClickHouse Cloud 콘솔에 저장된 모든 SQL 쿼리로부터 API 엔드포인트를 직접 생성할 수 있습니다. 네이티브 드라이버로 ClickHouse Cloud 서비스에 연결하지 않아도 HTTP를 통해 API 엔드포인트에 액세스하여 저장된 쿼리를 실행할 수 있습니다.

<div id="quick-start-guide">
  ## 사전 요구 사항
</div>

계속하기 전에 다음 항목이 준비되어 있는지 확인하십시오:

* 적절한 권한이 부여된 API Key
* 관리자 Console 역할

아직 없다면 이 가이드를 따라 [API Key를 생성](/docs/ko/products/cloud/features/admin-features/api/openapi)할 수 있습니다.

<Info>
  **최소 권한**

  API 엔드포인트를 쿼리하려면 API Key에 `Query Endpoints` 서비스 액세스가 포함된 `Member` 조직 역할이 필요합니다. 데이터베이스 역할은 엔드포인트를 생성할 때 구성됩니다.
</Info>

<Steps>
  <Step title="저장된 쿼리 만들기" id="creating-a-saved-query">
    이미 저장된 쿼리가 있으면 이 단계는 건너뛰어도 됩니다.

    Open a new query tab. For demonstration purposes, we'll use the [youtube dataset](/docs/ko/get-started/sample-datasets/youtube-dislikes), which contains approximately 4.5 billion records.
    Follow the steps in section ["Create table"](/docs/ko/get-started/sample-datasets/youtube-dislikes#create-the-table) to create the table on your Cloud service and insert data to it.

    <Tip>
      **`LIMIT` the number of rows**

      The example dataset tutorial inserts a lot of data - 4.65 billion rows which can take some time to insert.
      For the purposes of this guide we recommend to use the `LIMIT` clause to insert a smaller amount of data,
      for example 10 million rows.
    </Tip>

    As an example query, we'll return the top 10 uploaders by average views per video in a user-inputted `year` parameter.

    ```sql highlight={11} theme={null}
    WITH sum(view_count) AS view_sum,
      round(view_sum / num_uploads, 2) AS per_upload
    SELECT
      uploader,
      count() AS num_uploads,
      formatReadableQuantity(view_sum) AS total_views,
      formatReadableQuantity(per_upload) AS views_per_video
    FROM
      youtube
    WHERE
      toYear(upload_date) = {year: UInt16}
    GROUP BY uploader
    ORDER BY per_upload desc
      LIMIT 10
    ```

    Note that this query contains a parameter (`year`) which is highlighted in the snippet above.
    You can specify 쿼리 매개변수 using `{ }` together with the type of the parameter.
    The SQL console query editor automatically detects ClickHouse 쿼리 매개변수 expressions and provides an input for each parameter.

    Let's quickly run this query to make sure that it works by specifying the year `2010` in the 쿼리 변수 input box on the right side of the SQL editor:

    <Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/sqlconsole/endpoints-testquery.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=c69ce673072df222090c4225ef1e9ea5" size="md" alt="Test the example query" width="4040" height="1092" data-path="images/cloud/sqlconsole/endpoints-testquery.webp" />

    Next, save the query:

    <Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/sqlconsole/endpoints-savequery.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=a789eaf612341685c21a5931d0f9c902" size="md" alt="Save example query" width="2116" height="1024" data-path="images/cloud/sqlconsole/endpoints-savequery.webp" />

    More documentation around 저장된 쿼리 can be found in section ["Saving a query"](/docs/ko/products/cloud/features/sql-console-features/sql-console#saving-a-query).
  </Step>

  <Step title="Configuring the Query API 엔드포인트" id="configuring-the-query-api-endpoint">
    Query API endpoint can be configured directly from query view by clicking the **Share** button and selecting `API Endpoint`.
    You'll be prompted to specify which API Keys should be able to access the endpoint:

    <Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/sqlconsole/endpoints-configure.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=8c08ed17a292a6237f6bf984b20b1c20" size="md" alt="Configure query endpoint" width="1640" height="1684" data-path="images/cloud/sqlconsole/endpoints-configure.webp" />

    After selecting an API Key, you will be asked to:

    * Select the 데이터베이스 역할 that will be used to run the query (`Full access`, `Read only` or `Create a custom role`)
    * Specify cross-origin resource sharing (CORS) allowed domains

    After selecting these options, the Query API 엔드포인트 will automatically be provisioned.

    An example `curl` command will be displayed so you can send a test request:

    <Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/sqlconsole/endpoints-completed.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=7fc30918496bfc1f435120296032f4e6" size="md" alt="Endpoint curl command" width="1604" height="932" data-path="images/cloud/sqlconsole/endpoints-completed.webp" />

    The curl command displayed in the interface is given below for convenience:

    ```bash theme={null}
    curl -H "Content-Type: application/json" -s --user '<key_id>:<key_secret>' '<API-endpoint>?format=JSONEachRow&param_year=<value>'
    ```
  </Step>

  <Step title="Query API parameters" id="query-api-parameters">
    쿼리의 쿼리 매개변수 can be specified with the syntax `{parameter_name: type}`. These parameters will be automatically detected and the example request payload will contain a `queryVariables` object through which you can pass these parameters.
  </Step>

  <Step title="Testing and monitoring" id="testing-and-monitoring">
    Once a Query API 엔드포인트 is created, you can test that it works by using `curl` or any other HTTP client:

    <Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/sqlconsole/endpoints-curltest.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=86e61ea49e78a2cd370a7ffe458fa424" size="md" alt="endpoint curl test" width="987" height="203" data-path="images/cloud/sqlconsole/endpoints-curltest.webp" />

    After you've sent your first request, a new button should appear immediately to the right of the **Share** button. Clicking it will open a flyout containing monitoring data about the query:

    <Image img="https://mintcdn.com/private-7c7dfe99/7KTNIE_ER4ouwRNt/images/cloud/sqlconsole/endpoints-monitoring.webp?fit=max&auto=format&n=7KTNIE_ER4ouwRNt&q=85&s=23569c1ba80160d732ddcf77e5c3e67b" size="sm" alt="Endpoint monitoring" width="1644" height="2432" data-path="images/cloud/sqlconsole/endpoints-monitoring.webp" />
  </Step>
</Steps>

<div id="implementation-details">
  ## 구현 세부 사항
</div>

이 엔드포인트는 저장된 Query API endpoint에서 쿼리를 실행합니다.
여러 버전, 유연한 응답 포맷, 매개변수화된 쿼리, 선택적 스트리밍 응답(버전 2만 지원)을 지원합니다.

**엔드포인트:**

```text theme={null}
GET /query-endpoints/{queryEndpointId}/run
POST /query-endpoints/{queryEndpointId}/run
```

<div id="http-methods">
  ### HTTP 메서드
</div>

| 메서드      | 사용 사례                    | 매개변수                                           |
| -------- | ------------------------ | ---------------------------------------------- |
| **GET**  | 매개변수가 있는 단순 쿼리           | URL 매개변수(`?param_name=value`)를 통해 쿼리 변수를 전달합니다 |
| **POST** | 복잡한 쿼리이거나 요청 본문을 사용하는 경우 | 요청 본문(`queryVariables` 객체)으로 쿼리 변수를 전달합니다      |

**GET를 사용하는 경우:**

* 복잡하게 중첩된 데이터가 없는 단순 쿼리
* 매개변수를 URL 인코딩하기 쉬운 경우
* 캐싱이 HTTP GET의 의미 체계로 이점을 얻을 수 있는 경우

**POST를 사용하는 경우:**

* 복잡한 쿼리 변수(배열, 객체, 긴 문자열)
* 보안 또는 개인정보 보호를 위해 요청 본문을 사용하는 것이 바람직한 경우
* 스트리밍 파일 업로드 또는 대용량 데이터

<div id="authentication">
  ### 인증
</div>

**필수:** 예
**메서드:** OpenAPI Key/Secret 기반 Basic Auth
**권한:** 쿼리 엔드포인트에 대한 적절한 권한

<div id="request-configuration">
  ### 요청 구성
</div>

<div id="url-params">
  #### URL 매개변수
</div>

| 매개변수              | 필수    | 설명                   |
| ----------------- | ----- | -------------------- |
| `queryEndpointId` | **예** | 실행할 쿼리 엔드포인트의 고유 식별자 |

<div id="query-params">
  #### 쿼리 매개변수
</div>

| 매개변수                  | 필수  | 설명                                                               | 예시                       |
| --------------------- | --- | ---------------------------------------------------------------- | ------------------------ |
| `format`              | 아니요 | 응답 포맷(모든 ClickHouse 포맷 지원)                                       | `?format=JSONEachRow`    |
| `param_:name`         | 아니요 | 요청 본문이 스트림일 때 사용하는 쿼리 변수입니다. `:name`을 변수 이름으로 바꾸십시오              | `?param_year=2024`       |
| `request_timeout`     | 아니요 | 쿼리 타임아웃(밀리초, 기본값: 30000)                                         | `?request_timeout=60000` |
| `:clickhouse_setting` | 아니요 | 지원되는 모든 [ClickHouse 설정](/docs/ko/reference/settings/session-settings) | `?max_threads=8`         |

<div id="headers">
  #### 헤더
</div>

| 헤더                              | 필수 여부 | 설명                                     | 값                              |
| ------------------------------- | ----- | -------------------------------------- | ------------------------------ |
| `x-clickhouse-endpoint-version` | 아니요   | endpoint 버전을 지정합니다                     | `1` 또는 `2` (기본값: 마지막으로 저장된 버전) |
| `x-clickhouse-endpoint-upgrade` | 아니요   | endpoint 버전 업그레이드를 실행합니다(버전 헤더와 함께 사용) | 업그레이드 시 `1`                    |

***

<div id="request-body">
  ### 요청 본문
</div>

<div id="params">
  #### 매개변수
</div>

| 매개변수             | 유형     | 필수  | 설명          |
| ---------------- | ------ | --- | ----------- |
| `queryVariables` | 객체     | 아니요 | 쿼리에서 사용할 변수 |
| `format`         | string | 아니요 | 응답 포맷       |

<div id="supported-formats">
  #### 지원되는 포맷
</div>

| 버전             | 지원 포맷                                                                                                                                                                    |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **버전 2**       | ClickHouse에서 지원하는 모든 포맷                                                                                                                                                  |
| **버전 1 (제한적)** | TabSeparated <br /> TabSeparatedWithNames <br /> TabSeparatedWithNamesAndTypes <br /> JSON <br /> JSONEachRow <br /> CSV <br /> CSVWithNames <br /> CSVWithNamesAndTypes |

***

<div id="responses">
  ### 응답
</div>

<div id="success">
  #### 성공
</div>

**상태:** `200 OK`
쿼리가 정상적으로 실행되었습니다.

<div id="error-codes">
  #### 오류 코드
</div>

| 상태 코드              | 설명                      |
| ------------------ | ----------------------- |
| `400 Bad Request`  | 요청 형식이 올바르지 않습니다        |
| `401 Unauthorized` | 인증 정보가 없거나 필요한 권한이 없습니다 |
| `404 Not Found`    | 지정한 쿼리 엔드포인트를 찾을 수 없습니다 |

<div id="error-handling-best-practices">
  #### 오류 처리 모범 사례
</div>

* 요청에 유효한 인증 자격 증명이 포함되어 있는지 확인하세요
* 전송하기 전에 `queryEndpointId`와 `queryVariables`를 검증하세요
* 적절한 오류 메시지와 함께 안정적으로 오류를 처리하도록 구현하세요

***

<div id="upgrading-endpoint-versions">
  ### 엔드포인트 버전 업그레이드
</div>

버전 1에서 버전 2로 업그레이드하려면 다음을 수행하세요.

1. `x-clickhouse-endpoint-upgrade` 헤더를 `1`로 설정해 포함합니다
2. `x-clickhouse-endpoint-version` 헤더를 `2`로 설정해 포함합니다

이렇게 하면 다음과 같은 버전 2 기능을 사용할 수 있습니다.

* 모든 ClickHouse 포맷 지원
* 응답 스트리밍 capability
* 향상된 성능 및 기능

<div id="examples">
  ## 예시
</div>

<div id="basic-request">
  ### 기본 요청
</div>

**Query API 엔드포인트 SQL:**

```sql theme={null}
SELECT database, name AS num_tables FROM system.tables LIMIT 3;
```

<div id="version-1">
  #### 버전 1
</div>

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run' \
    --user '<openApiKeyId:openApiKeySecret>' \
    -H 'Content-Type: application/json' \
    -d '{ "format": "JSONEachRow" }'
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    fetch(
      "https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run",
      {
        method: "POST",
        headers: {
          Authorization: "Basic <base64_encoded_credentials>",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          format: "JSONEachRow",
        }),
      }
    )
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((error) => console.error("Error:", error));
    ```

    ```json title="응답" theme={null}
    {
      "data": {
        "columns": [
          {
            "name": "database",
            "type": "String"
          },
          {
            "name": "num_tables",
            "type": "String"
          }
        ],
        "rows": [
          ["INFORMATION_SCHEMA", "COLUMNS"],
          ["INFORMATION_SCHEMA", "KEY_COLUMN_USAGE"],
          ["INFORMATION_SCHEMA", "REFERENTIAL_CONSTRAINTS"]
        ]
      }
    }
    ```
  </Tab>
</Tabs>

<div id="version-2">
  #### 버전 2
</div>

<Tabs>
  <Tab title="GET (cURL)">
    ```bash theme={null}
    curl 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONEachRow' \
    --user '<openApiKeyId:openApiKeySecret>' \
    -H 'x-clickhouse-endpoint-version: 2'
    ```

    ```application/x-ndjson title="응답" theme={null}
    {"database":"INFORMATION_SCHEMA","num_tables":"COLUMNS"}
    {"database":"INFORMATION_SCHEMA","num_tables":"KEY_COLUMN_USAGE"}
    {"database":"INFORMATION_SCHEMA","num_tables":"REFERENTIAL_CONSTRAINTS"}
    ```
  </Tab>

  <Tab title="POST (cURL)">
    ```bash theme={null}
    curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONEachRow' \
    --user '<openApiKeyId:openApiKeySecret>' \
    -H 'Content-Type: application/json' \
    -H 'x-clickhouse-endpoint-version: 2'
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    fetch(
      "https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONEachRow",
      {
        method: "POST",
        headers: {
          Authorization: "Basic <base64_encoded_credentials>",
          "Content-Type": "application/json",
          "x-clickhouse-endpoint-version": "2",
        },
      }
    )
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((error) => console.error("Error:", error));
    ```

    ```application/x-ndjson title="응답" theme={null}
    {"database":"INFORMATION_SCHEMA","num_tables":"COLUMNS"}
    {"database":"INFORMATION_SCHEMA","num_tables":"KEY_COLUMN_USAGE"}
    {"database":"INFORMATION_SCHEMA","num_tables":"REFERENTIAL_CONSTRAINTS"}
    ```
  </Tab>
</Tabs>

<div id="request-with-query-variables-and-version-2-on-jsoncompacteachrow-format">
  ### 쿼리 변수와 JSONCompactEachRow 포맷 버전 2를 사용한 요청
</div>

**Query API 엔드포인트 SQL:**

```sql theme={null}
SELECT name, database FROM system.tables WHERE match(name, {tableNameRegex: String}) AND database = {database: String};
```

<Tabs>
  <Tab title="GET (cURL)">
    ```bash theme={null}
    curl 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONCompactEachRow&param_tableNameRegex=query.*&param_database=system' \
    --user '<openApiKeyId:openApiKeySecret>' \
    -H 'x-clickhouse-endpoint-version: 2'
    ```

    ```application/x-ndjson title="응답" theme={null}
    ["query_cache", "system"]
    ["query_log", "system"]
    ["query_views_log", "system"]
    ```
  </Tab>

  <Tab title="POST (cURL)">
    ```bash theme={null}
    curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONCompactEachRow' \
    --user '<openApiKeyId:openApiKeySecret>' \
    -H 'Content-Type: application/json' \
    -H 'x-clickhouse-endpoint-version: 2' \
    -d '{ "queryVariables": { "tableNameRegex": "query.*", "database": "system" } }'
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    fetch(
      "https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONCompactEachRow",
      {
        method: "POST",
        headers: {
          Authorization: "Basic <base64_encoded_credentials>",
          "Content-Type": "application/json",
          "x-clickhouse-endpoint-version": "2",
        },
        body: JSON.stringify({
          queryVariables: {
            tableNameRegex: "query.*",
            database: "system",
          },
        }),
      }
    )
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((error) => console.error("Error:", error));
    ```

    ```application/x-ndjson title="응답" theme={null}
    ["query_cache", "system"]
    ["query_log", "system"]
    ["query_views_log", "system"]
    ```
  </Tab>
</Tabs>

<div id="request-with-array-in-the-query-variables-that-inserts-data-into-a-table">
  ### 쿼리 변수에 배열이 포함되어 있고 테이블에 데이터를 삽입하는 요청
</div>

**테이블 SQL:**

```SQL theme={null}
CREATE TABLE default.t_arr
(
    `arr` Array(Array(Array(UInt32)))
)
ENGINE = MergeTree
ORDER BY tuple()
```

**Query API 엔드포인트 SQL:**

```sql theme={null}
INSERT INTO default.t_arr VALUES ({arr: Array(Array(Array(UInt32)))});
```

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run' \
    --user '<openApiKeyId:openApiKeySecret>' \
    -H 'Content-Type: application/json' \
    -H 'x-clickhouse-endpoint-version: 2' \
    -d '{
      "queryVariables": {
        "arr": [[[12, 13, 0, 1], [12]]]
      }
    }'
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    fetch(
      "https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run",
      {
        method: "POST",
        headers: {
          Authorization: "Basic <base64_encoded_credentials>",
          "Content-Type": "application/json",
          "x-clickhouse-endpoint-version": "2",
        },
        body: JSON.stringify({
          queryVariables: {
            arr: [[[12, 13, 0, 1], [12]]],
          },
        }),
      }
    )
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((error) => console.error("Error:", error));
    ```

    ```text title="응답" theme={null}
    OK
    ```
  </Tab>
</Tabs>

<div id="request-with-clickhouse-settings-max_threads-set-to-8">
  ### ClickHouse 설정 `max_threads`를 8로 지정한 요청
</div>

**Query API 엔드포인트 SQL:**

```sql theme={null}
SELECT * FROM system.tables;
```

<Tabs>
  <Tab title="GET (cURL)">
    ```bash theme={null}
    curl 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?max_threads=8' \
    --user '<openApiKeyId:openApiKeySecret>' \
    -H 'x-clickhouse-endpoint-version: 2'
    ```
  </Tab>

  <Tab title="POST (cURL)">
    ```bash theme={null}
    curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?max_threads=8,' \
    --user '<openApiKeyId:openApiKeySecret>' \
    -H 'Content-Type: application/json' \
    -H 'x-clickhouse-endpoint-version: 2' \
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    fetch(
      "https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?max_threads=8",
      {
        method: "POST",
        headers: {
          Authorization: "Basic <base64_encoded_credentials>",
          "Content-Type": "application/json",
          "x-clickhouse-endpoint-version": "2",
        },
      }
    )
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((error) => console.error("Error:", error));
    ```
  </Tab>
</Tabs>

<div id="request-and-parse-the-response-as-a-stream">
  ### 응답을 요청해 스트림으로 파싱하기
</div>

**Query API 엔드포인트 SQL:**

```sql theme={null}
SELECT name, database FROM system.tables;
```

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    async function fetchAndLogChunks(
      url: string,
      openApiKeyId: string,
      openApiKeySecret: string
    ) {
      const auth = Buffer.from(`${openApiKeyId}:${openApiKeySecret}`).toString(
        "base64"
      );

      const headers = {
        Authorization: `Basic ${auth}`,
        "x-clickhouse-endpoint-version": "2",
      };

      const response = await fetch(url, {
        headers,
        method: "POST",
        body: JSON.stringify({ format: "JSONEachRow" }),
      });

      if (!response.ok) {
        console.error(`HTTP error! Status: ${response.status}`);
        return;
      }

      const reader = response.body as unknown as Readable;
      reader.on("data", (chunk) => {
        console.log(chunk.toString());
      });

      reader.on("end", () => {
        console.log("Stream ended.");
      });

      reader.on("error", (err) => {
        console.error("Stream error:", err);
      });
    }

    const endpointUrl =
      "https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONEachRow";
    const openApiKeyId = "<myOpenApiKeyId>";
    const openApiKeySecret = "<myOpenApiKeySecret>";
    // 사용 예시
    fetchAndLogChunks(endpointUrl, openApiKeyId, openApiKeySecret).catch((err) =>
      console.error(err)
    );
    ```

    ```shell title="출력" theme={null}
    > npx tsx index.ts
    > {"name":"COLUMNS","database":"INFORMATION_SCHEMA"}
    > {"name":"KEY_COLUMN_USAGE","database":"INFORMATION_SCHEMA"}
    ...
    > Stream ended.
    ```
  </Tab>
</Tabs>

<div id="insert-a-stream-from-a-file-into-a-table">
  ### 파일에서 스트림을 테이블에 삽입하기
</div>

다음 내용으로 `./samples/my_first_table_2024-07-11.csv` 파일을 생성하세요:

```csv theme={null}
"user_id","json","name"
"1","{""name"":""John"",""age"":30}","John"
"2","{""name"":""Jane"",""age"":25}","Jane"
```

**테이블 생성 SQL:**

```sql theme={null}
create table default.my_first_table
(
    user_id String,
    json String,
    name String,
) ENGINE = MergeTree()
ORDER BY user_id;
```

**Query API 엔드포인트 SQL:**

```sql theme={null}
INSERT INTO default.my_first_table
```

```bash theme={null}
cat ./samples/my_first_table_2024-07-11.csv | curl --user '<openApiKeyId:openApiKeySecret>' \
                                                   -X POST \
                                                   -H 'Content-Type: application/octet-stream' \
                                                   -H 'x-clickhouse-endpoint-version: 2' \
                                                   "https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=CSV" \
                                                   --data-binary @-
```
