---
title: Value.NativeQuery – รัน Native SQL Query ตรงจาก Power Query
url: https://www.thepexcel.com/functions/power-query/value-functions/value-nativequery/
type: function-explainer
program: Power Query
syntax: "Value.NativeQuery(target as any, query as text, optional parameters as any, optional options as nullable record) as any"
date: 2025-12-12
updated: 2025-12-23
scores:
  popularity: 5
  difficulty: 7
  usefulness: 6
---

# Value.NativeQuery – รัน Native SQL Query ตรงจาก Power Query

> Value.NativeQuery ใช้รันคำสั่ง SQL โดยตรงกับฐานข้อมูล เช่น SQL Server, PostgreSQL, BigQuery โดยสามาร

## คำอธิบาย

Value.NativeQuery ใช้รันคำสั่ง SQL โดยตรงกับฐานข้อมูล เช่น SQL Server, PostgreSQL, BigQuery โดยสามารถส่ง parameters และเปิด Query Folding ได้

## Syntax

```excel
Value.NativeQuery(target as any, query as text, optional parameters as any, optional options as nullable record) as any
```

## Arguments

| Name | Required | Type | Default | Description |
| --- | --- | --- | --- | --- |
| target | Yes | any |  | Data source connection ที่ต้องการรัน query (เช่น ผลลัพธ์จาก Sql.Database หรือ Sql.Databases) |
| query | Yes | text |  | คำสั่ง SQL หรือ native query ของ data source นั้นๆ เช่น T-SQL สำหรับ SQL Server |
| parameters | No | any | null | Record หรือ List ของ parameter values สำหรับ parameterized query (ใช้ @ สำหรับ SQL Server หรือ ? สำหรับบาง database) |
| options | No | nullable record | null | Record ของ options เช่น [EnableFolding = true] เพื่อเปิด Query Folding หรือ [PreserveTypes = true] เพื่อรักษา data type จาก database |

## ตัวอย่าง

### 1. ตัวอย่างพื้นฐาน - SELECT ข้อมูลตรงจากฐานข้อมูล

```excel
let
    Source = Sql.Database("localhost", "AdventureWorks"),
    Query = Value.NativeQuery(
        Source,
        "SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ListPrice > 100"
    )
in
    Query
```

**ผลลัพธ์:** `Table ของ Product ที่มีราคามากกว่า 100`

รัน SELECT query ตรงๆ กับ SQL Server โดยไม่ต้องผ่าน Table.SelectRows เลย เขียน SQL ได้เต็มรูปแบบตามที่ต้องการ Power Query ส่ง query นี้ไปรันที่ server โดยตรง ประมวลผลได้เร็วกว่าการโหลดข้อมูลทั้งหมดมาก่อน

### 2. ใช้ Parameterized Query ป้องกัน SQL Injection

```excel
let
    Source = Sql.Database("localhost", "AdventureWorks"),
    MinPrice = 500,
    MaxPrice = 2000,
    Query = Value.NativeQuery(
        Source,
        "SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ListPrice BETWEEN @minprice AND @maxprice ORDER BY ListPrice DESC",
        [minprice = MinPrice, maxprice = MaxPrice]
    )
in
    Query
```

**ผลลัพธ์:** `Table ของ Product ที่ราคาระหว่าง 500-2000 จัดเรียงจากราคาสูงสุด`

ส่ง parameter @minprice และ @maxprice ผ่าน record แทนการต่อ string ปลอดภัยจาก SQL Injection เพราะ parameter จะถูก escape อัตโนมัติ โค้ดอ่านง่ายและสามารถใช้ซ้ำได้โดยเปลี่ยนค่าตัวแปร

### 3. เปิด Query Folding ด้วย EnableFolding = true

```excel
let
    Source = Sql.Database("localhost", "AdventureWorks"),
    Query = Value.NativeQuery(
        Source,
        "SELECT * FROM Sales.SalesOrderHeader WHERE YEAR(OrderDate) = 2024",
        null,
        [EnableFolding = true]
    ),
    Filtered = Table.SelectRows(Query, each [TotalDue] > 10000),
    Sorted = Table.Sort(Filtered, {{"OrderDate", Order.Descending}})
in
    Sorted
```

**ผลลัพธ์:** `Table ของ Orders ปี 2024 ที่ TotalDue > 10000 เรียงตามวันที่ล่าสุด (ทั้งหมดทำที่ Server)`

EnableFolding = true ทำให้ step ถัดไป (SelectRows, Sort) ถูกแปลงเป็น SQL subquery และส่งไปรันที่ Server ด้วย แทนโหลดข้อมูลทั้งหมดมากลับเครื่องก่อน ลดการถ่ายโอนข้อมูลอย่างมาก ประสิทธิภาพดีขึ้นเห็นชัด

### 4. ใช้ CTE และ Window Function (ROW_NUMBER)

```excel
let
    Source = Sql.Database("localhost", "AdventureWorks"),
    Query = Value.NativeQuery(
        Source,
        "WITH TopProducts AS (
            SELECT ProductID, Name, ListPrice, CategoryID,
                   ROW_NUMBER() OVER (PARTITION BY CategoryID ORDER BY ListPrice DESC) AS RankInCategory
            FROM Production.Product
        )
        SELECT * FROM TopProducts WHERE RankInCategory <= 5",
        null,
        [EnableFolding = true]
    )
in
    Query
```

**ผลลัพธ์:** `Table ของ 5 สินค้าที่ราคาสูงสุดในแต่ละหมวดหมู่ พร้อม RankInCategory`

CTE (WITH clause) และ ROW_NUMBER() เป็น feature ที่ Power Query UI ไม่รองรับโดยตรง Value.NativeQuery ช่วยให้เขียน advanced SQL ได้เต็มที่ เหมาะสำหรับการดึงข้อมูลที่มีเงื่อนไขซับซ้อน ใช้ PARTITION BY เพื่อจัดลำดับภายในกลุ่ม

## หมายเหตุเพิ่มเติม

- ใช้ EnableFolding = true เสมอถ้าต้องการให้ step ถัดไปอย่าง filter หรือ sort ถูกส่งไปรันที่ Server ช่วยเรื่องความเร็วได้มากโดยเฉพาะกับข้อมูลขนาดใหญ่

- ใช้ [PreserveTypes = true] ถ้าต้องการให้ข้อมูลที่ดึงมามีชนิดข้อมูลตรงกับที่กำหนดไว้ใน database ไม่ถูกแปลงอัตโนมัติ

- ตรวจสอบว่า Query Folding ทำงานได้หรือไม่ ด้วยการคลิกขวาที่ step แล้วดู View Native Query ถ้า option นี้เปิดใช้ได้แสดงว่า fold สำเร็จ

- ใช้ parameterized query แทนการต่อ string เสมอ เพื่อความปลอดภัยจาก SQL Injection และทำให้โค้ดอ่านง่ายขึ้น

- SQL Server ใช้ @param แต่บาง database เช่น MySQL ใช้ ? แทน ให้ตรวจสอบรูปแบบที่ถูกต้องตาม database ที่ใช้งานครับ

## คำถามที่พบบ่อย

**Q: EnableFolding = true ทำอะไร?**

ทำให้ step ที่ตามมา เช่น Table.SelectRows หรือ Table.Sort สามารถถูกแปลงเป็น SQL และส่งไปรันที่ Server ได้ แทนที่จะต้องโหลดข้อมูลทั้งหมดมาก่อนแล้วค่อยประมวลผลในเครื่อง ช่วยเรื่องความเร็วได้มากโดยเฉพาะถ้าข้อมูลมีหลายล้านแถว ถ้าไม่เปิด option นี้ native query จะ fold แค่ตัวมันเอง ส่วน step ถัดไปจะถูกประมวลผลใน Power Query ซึ่งช้ากว่ามากครับ

**Q: ทำไมมี warning เรื่อง Native Query?**

Power Query จะแจ้งเตือนเรื่องความปลอดภัยทุกครั้งที่ใช้ native query เพราะคำสั่งที่เขียนเองอาจมีคำสั่งอันตรายที่สร้างความเสียหายต่อข้อมูลได้ เราต้องกด Edit Permission แล้วเลือก Run เพื่ออนุญาตให้รันได้ นี่เป็นเรื่องปกติและจำเป็นเพื่อความปลอดภัยของข้อมูลและระบบครับ

**Q: ใช้กับ Database อะไรได้บ้าง?**

รองรับหลาย database ได้แก่ SQL Server, PostgreSQL, Oracle, MySQL, Snowflake, Google BigQuery, Amazon Redshift, SAP HANA และ Dataverse (ที่เปิด Enhanced Compute) แต่ละ database อาจมีรูปแบบการเขียน SQL และ parameter placeholder ที่แตกต่างกัน เช่น SQL Server ใช้ @param แต่บางตัวอาจใช้ ? แทน ต้องศึกษาเพิ่มเติมตาม database ที่ใช้งานครับ

**Q: ใช้กับ DirectQuery ใน Power BI ได้ไหม?**

ไม่ได้ครับ Value.NativeQuery ใช้ได้เฉพาะ Import mode เท่านั้น ถ้าพยายามใช้กับ DirectQuery จะได้ข้อความแสดงข้อผิดพลาด ถ้าต้องการใช้ native query ใน DirectQuery ให้ตั้งค่าตอนเชื่อมต่อ database แทน โดยเลือกใส่ native query ใน connector settings ตั้งแต่ต้นครับ

**Q: Parameters สามารถเปลี่ยนตาม Slicer ได้ไหม?**

ไม่ได้โดยตรงครับ เพราะ parameters ต้องกำหนดค่าตอนที่ query ถูกประมวลผล ซึ่งเกิดขึ้นก่อนที่รายงานจะโหลด ถ้าต้องการให้ผู้ใช้สามารถเลือกกรองข้อมูลจาก slicer ได้ แนะนำให้ใช้ DAX filter แทน หรือถ้าข้อมูลไม่ใหญ่มากก็โหลดข้อมูลทั้งหมดมาแล้วใช้ slicer filter ใน report แทนครับ

## แหล่งข้อมูลเพิ่มเติม

- [Microsoft Learn: Value.NativeQuery](https://learn.microsoft.com/en-us/powerquery-m/value-nativequery) _(official)_
- [Microsoft Learn: Query folding on native queries](https://learn.microsoft.com/en-us/power-query/native-query-folding) _(official)_
- [Chris Webb: Query Folding with EnableFolding](https://blog.crossjoin.co.uk/2021/02/21/query-folding-on-sql-queries-in-power-query-using-value-nativequery-and-enablefoldingtrue/) _(article)_

---

_Source: [https://www.thepexcel.com/functions/power-query/value-functions/value-nativequery/](https://www.thepexcel.com/functions/power-query/value-functions/value-nativequery/)_
