

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 連線至 Microsoft SQL Server 資料來源
<a name="using-microsoft-sql-server-in-AMG"></a>

 使用 Microsoft SQL Server (MSSQL) 資料來源查詢和視覺化任何 Microsoft SQL Server 2005 或更新版本的資料，包括 Microsoft Azure SQL Database。

**重要**  
Grafana 8.0 版會變更 Microsoft SQL Server、Postgres 和 MySQL 的資料框架基礎資料結構。因此，時間序列查詢結果會以寬格式傳回。如需詳細資訊，請參閱 Grafana 資料影格文件中的[寬格式](https://grafana.com/developers/plugin-tools/introduction/data-frames#wide-format)。  
若要讓您的視覺化像以前一樣運作，您可能需要執行一些手動遷移。一個解決方案記錄在 Github 上的 [Postgres/MySQL/MSSQL：中斷 v8.0 中與時間序列查詢和資料欄排序相關的變更](https://github.com/grafana/grafana/issues/35534)。

## 新增資料來源
<a name="mssql-adding-the-data-source"></a>

1.  選擇頂端標頭中的 Grafana 圖示，開啟側邊選單。

1.  在連結下方的側邊選單中，****您應該會找到**資料來源**連結。

1.  選擇頂端標頭中的 **\+ 新增資料來源**按鈕。

1.  從**類型**下拉式清單中選取 **Microsoft SQL Server**。

### 資料來源選項
<a name="mssql-data-source-options"></a>


|  名稱  |  描述  | 
| --- | --- | 
|  Name  |  資料來源名稱。這是您在面板和查詢中看到資料來源的方式。 | 
|  Default  |  預設資料來源表示新面板會預先選取。 | 
|  Host  |  MSSQL 執行個體的 IP 地址/主機名稱和選用連接埠。如果省略連接埠，則會使用預設的 1433。 | 
|  Database  |  MSSQL 資料庫的名稱。 | 
|  User  |  資料庫使用者的登入/使用者名稱。 | 
|  Password  |  資料庫使用者的密碼。 | 
|  Encrypt  |  此選項會決定安全 SSL TCP/IP 連線是否會與伺服器交涉，預設 false(Grafana v5.4\+)。 | 
|  Max open  |  預設 unlimited(Grafana v5.4\+) 資料庫的開啟連線數目上限。 | 
|  Max idle  |  預設閒置連線集區中的連線數目上限 2(Grafana v5.4\+)。 | 
|  Max lifetime  |  可以重複使用連線的秒數上限，預設為 14400/4 小時。 | 

### 最短時間間隔
<a name="mssql-min-time-interval"></a>

 `$_interval` `$_interval_ms` 變數的下限。建議設定為寫入頻率，例如，`1m`如果資料每分鐘寫入一次。也可以在資料來源選項下的儀表板面板中覆寫/設定此選項。此值的格式**必須是**數字，後面接著有效的時間識別符；例如 `1m`(1 分鐘） 或 `30s`(30 秒）。支援下列時間識別碼。


|  識別符  |  Description  | 
| --- | --- | 
|  y  |  年  | 
|  M  |  月  | 
|  w  |  週  | 
|  d  |  天  | 
|  h  |  小時  | 
|  m  |  分鐘  | 
|  s  |  秒  | 
|  ms  |  毫秒  | 

### 資料庫使用者許可
<a name="mssql-database-user-permissions-important"></a>

**重要**  
 您在新增資料來源時指定的資料庫使用者，應僅獲得您要查詢之指定資料庫和資料表的 SELECT 許可。Grafana 不會驗證查詢是否安全。查詢可包含任何 SQL 陳述式。例如，`DROP TABLE user;`會執行 `DELETE FROM user;`和 等陳述式。為了防止這種情況，強烈建議您建立具有受限許可的特定 MSSQL 使用者。

 下列範例程式碼顯示建立具有受限許可的特定 MSSQL 使用者。

```
 CREATE USER grafanareader WITH PASSWORD 'password'
 GRANT SELECT ON dbo.YourTable3 TO grafanareader
```

 確定使用者未從公有角色取得任何不需要的許可。

### 已知問題
<a name="mssql-known-issues"></a>

 如果您使用的是舊版 Microsoft SQL Server，例如 2008 和 2008R2，您可能需要停用加密才能連線。如果可能，我們建議您使用最新的 Service Pack，以獲得最佳相容性。

## 查詢編輯器
<a name="mssql-query-editor"></a>

 您可以在圖形、Singlestat 或資料表面板的編輯模式中的指標索引標籤中找到 MSSQL 查詢編輯器。您可以選擇面板標題，然後選擇編輯，以進入編輯模式。編輯器可讓您定義 SQL 查詢，以選取要視覺化的資料。

1.  選取*格式化為* `Time series`（用於圖形或 Singlestat 面板等） 或 `Table`（用於資料表面板等）。

1.  這是您寫入 SQL 查詢的實際編輯器。

1.  在查詢編輯器下方顯示 MSSQL 的說明區段。

1.  顯示已執行的 SQL 查詢。成功執行查詢後，會先提供 。

1.  新增額外的查詢，其中會顯示額外的查詢編輯器。

## 巨集
<a name="mssql-macros"></a>

 為了簡化語法並允許動態部分，例如日期範圍篩選條件，查詢可以包含巨集。


|  巨集範例  |  Description  | 
| --- | --- | 
|  $\_\_time(dateColumn)  |  將由表達式取代，以不時重新命名資料欄。例如，dateColumn 做為時間 。 | 
|  $\_\_timeEpoch(dateColumn)  |  將由表達式取代，將 DATETIME 資料欄類型轉換為 Unix 時間戳記，並將其重新命名為時間。例如，DATEDIFF（秒、"1970-01-01"、dateColumn) AS 時間。 | 
|  $\_\_timeFilter(dateColumn)  |  將由使用指定資料欄名稱的時間範圍篩選條件取代。例如，dateColumn BETWEEN "2017-04-21T05：01：17Z" AND "2017-04-21T05：06：17Z"。 | 
|  $\_\_timeFrom()  |  將由目前作用中時間選擇的開始取代。例如，「2017-04-21T05：01：17Z」。 | 
|  $\_\_timeTo()  |  將取代為目前作用中時間選擇的結尾。例如，「2017-04-21T05：06：17Z」。 | 
|  $\_\_timeGroup(dateColumn,'5m'[, fillvalue])  |  將由 GROUP BY 子句中可用的表達式取代。提供 NULL 或浮點數的 fillValue 會自動以該值填入時間範圍中的空序列。例如，CAST(ROUND(DATEDIFF(second， "1970-01-01"， time\_column)/300.0， 0) as bigint)\*300。 | 
|  $\_\_timeGroup(dateColumn,'5m', 0)  |  與上述相同，但使用填充參數，因此 grafana 會新增該系列中的遺失點，並使用 0 做為值。 | 
|  $\_\_timeGroup(dateColumn,'5m', NULL)  |  與上述相同，但 NULL 將用作遺失點的值。 | 
|  $\_\_timeGroup(dateColumn,'5m', previous)  |  與上述相同，但如果尚未看到 NULL，則會使用該序列中的上一個值作為填充值 （僅適用於 Grafana 5.3\+)。 | 

 查詢編輯器具有**產生的 SQL** 連結，會在查詢執行後，在面板編輯模式中顯示。選擇它，它會展開並顯示已執行的原始插補 SQL 字串。

## 資料表查詢
<a name="mssql-table-queries"></a>

 如果查詢選項設定為 ，**Format as******Table，則基本上您可以執行任何類型的 SQL 查詢。資料表面板會自動顯示查詢傳回的任何資料欄和資料列的結果。

 下列範例程式碼顯示資料庫資料表。

```
CREATE TABLE [event] (
  time_sec bigint,
  description nvarchar(100),
  tags nvarchar(100),
)
```

```
CREATE TABLE [mssql_types] (
  c_bit bit, c_tinyint tinyint, c_smallint smallint, c_int int, c_bigint bigint, c_money money, c_smallmoney smallmoney, c_numeric numeric(10,5),
  c_real real, c_decimal decimal(10,2), c_float float,
  c_char char(10), c_varchar varchar(10), c_text text,
  c_nchar nchar(12), c_nvarchar nvarchar(12), c_ntext ntext,
  c_datetime datetime,  c_datetime2 datetime2, c_smalldatetime smalldatetime, c_date date, c_time time, c_datetimeoffset datetimeoffset
)

INSERT INTO [mssql_types]
SELECT
  1, 5, 20020, 980300, 1420070400, '$20000.15', '£2.15', 12345.12,
  1.11, 2.22, 3.33,
  'char10', 'varchar10', 'text',
  N'☺nchar12☺', N'☺nvarchar12☺', N'☺text☺',
  GETDATE(), CAST(GETDATE() AS DATETIME2), CAST(GETDATE() AS SMALLDATETIME), CAST(GETDATE() AS DATE), CAST(GETDATE() AS TIME), SWITCHOFFSET(CAST(GETDATE() AS DATETIMEOFFSET), '-07:00')
```

 下列範例程式碼顯示查詢。

```
SELECT * FROM [mssql_types]
```

 您可以使用一般 `AS` SQL 資料欄選取語法來控制資料表面板資料欄的名稱，如下列範例程式碼所示。

```
SELECT
  c_bit as [column1], c_tinyint as [column2]
FROM
  [mssql_types]
```

 產生的資料表面板：

## 時間序列查詢
<a name="mssql-time-series-queries"></a>

 如果您**將格式**設定為**時間序列**，例如在圖形面板中使用，查詢必須有名為 的資料欄`time`，以秒為單位傳回 SQL 日期時間或任何代表 Unix epoch 的數值資料類型。您可以傳回名為 的資料欄`metric`，做為值資料欄的指標名稱。除了 `time`和 以外的任何資料欄`metric`都會視為值資料欄。如果您省略資料`metric`欄，值資料欄的名稱將是指標名稱。您可以選取多個值資料欄，每個資料欄的名稱都會做為指標。如果您傳回多個值資料欄和名為 的資料欄`metric`，則會使用此資料欄做為序列名稱的字首。

 時間序列查詢的結果集必須依時間排序。

 下列範例程式碼顯示資料庫資料表。

```
CREATE TABLE [event] (
  time_sec bigint,
  description nvarchar(100),
  tags nvarchar(100),
)
```

```
CREATE TABLE metric_values (
  time datetime,
  measurement nvarchar(100),
  valueOne int,
  valueTwo int,
)

INSERT metric_values (time, measurement, valueOne, valueTwo) VALUES('2018-03-15 12:30:00', 'Metric A', 62, 6)
INSERT metric_values (time, measurement, valueOne, valueTwo) VALUES('2018-03-15 12:30:00', 'Metric B', 49, 11)
...
INSERT metric_values (time, measurement, valueOne, valueTwo) VALUES('2018-03-15 13:55:00', 'Metric A', 14, 25)
INSERT metric_values (time, measurement, valueOne, valueTwo) VALUES('2018-03-15 13:55:00', 'Metric B', 48, 10)
```

 下列範例程式碼顯示一欄`value`和一`metric`欄。

```
SELECT
  time,
  valueOne,
  measurement as metric
FROM
  metric_values
WHERE
  $__timeFilter(time)
ORDER BY 1
```

 在圖形面板中使用上述查詢時，會產生兩個名為 `Metric A`和 的序列`Metric B`，其值為 `valueOne`，並`valueTwo`繪製在 上`time`。

 下列範例程式碼顯示多個`value`資料欄。

```
SELECT
  time,
  valueOne,
  valueTwo
FROM
  metric_values
WHERE
  $__timeFilter(time)
ORDER BY 1
```

 在圖形面板中使用上述查詢時，會產生兩個名為 `Metric A`和 的序列`Metric B`，其值為 `valueOne`，並`valueTwo`繪製在 上`time`。

 下列範例程式碼顯示使用 $\_\_timeGroup 巨集。

```
SELECT
  $__timeGroup(time, '3m') as time,
  measurement as metric,
  avg(valueOne)
FROM
  metric_values
WHERE
  $__timeFilter(time)
GROUP BY
  $__timeGroup(time, '3m'),
  measurement
ORDER BY 1
```

 在圖形面板中使用上一個查詢時，會產生兩個名為 `Metric A`和 的序列`Metric B`，其值為 `valueOne`，並`valueTwo`繪製在 上`time`。在三分鐘的時段內缺少值的任何兩個序列都會轉譯這兩行之間的線條。您會注意到右側的圖形永遠不會下降到零。

 下列範例程式碼顯示使用 $\_\_timeGroup 巨集，且填充參數設為零。

```
SELECT
  $__timeGroup(time, '3m', 0) as time,
  measurement as metric,
  sum(valueTwo)
FROM
  metric_values
WHERE
  $__timeFilter(time)
GROUP BY
  $__timeGroup(time, '3m'),
  measurement
ORDER BY 1
```

 在圖形面板中使用此查詢時，結果是兩個名為 `Metric A`和 的序列`Metric B`，加總以 `valueTwo`繪製`time`。任何在 3 分鐘內缺少值的序列都會有零的值，您會在右側的圖表中看到該值。

## 範本化
<a name="mssql-templating"></a>

 您可以在指標查詢中使用變數，而不是硬式編碼，例如伺服器、應用程式和感應器名稱。變數會顯示為儀表板頂端的下拉式清單選取方塊。您可以使用這些下拉式方塊來變更儀表板中顯示的資料。

 如需範本和範本變數的詳細資訊，請參閱 [範本和變數](templates-and-variables.md)。

### 查詢變數
<a name="mssql-query-variable"></a>

 如果您新增 類型的範本變數`Query`，您可以撰寫 MSSQL 查詢，以傳回如測量名稱、索引鍵名稱或顯示為下拉式清單選取方塊的索引鍵值等物件。

 例如，如果您在範本變數查詢**設定中指定這類查詢，您可以有一個變數，其中包含資料表中資料`hostname`欄的所有值。

```
SELECT hostname FROM host
```

 查詢可以傳回多個資料欄，Grafana 會自動從中建立清單。例如，下列查詢將傳回來自 `hostname`和 的值清單`hostname2`。

```
SELECT [host].[hostname], [other_host].[hostname2] FROM host JOIN other_host ON [host].[city] = [other_host].[city]
```

 另一個選項是可建立索引鍵/值變數的查詢。查詢應傳回兩個名為 `__text`和 的資料欄`__value`。`__text` 資料欄值應該是唯一的 （如果不是唯一的，則會使用第一個值）。下拉式清單中的選項會有文字和值，可讓您將易記的名稱做為文字，並將 ID 做為值。使用 `hostname`做為文字和 `id`做為值的範例查詢：

```
SELECT hostname __text, id __value FROM host
```

 您也可以建立巢狀變數。例如，如果您有另一個名為 的變數`region`。然後，您可以讓主機變數只顯示目前所選區域中具有此類查詢的主機 （如果 `region` 是多值變數，則使用`IN`比較運算子，而不是`=`比對多個值）。

```
SELECT hostname FROM host WHERE region IN ($region)
```

### 在查詢中使用變數
<a name="mssql-using-variables-in-queries"></a>

**注意**  
 只有在範本變數是 時，才會引用範本變數值`multi-value`。

 如果變數是多值變數，請使用`IN`比較運算子`=`，而不是比對多個值。

 有兩種語法：

 `$<varname>` 範本變數名為 的範例`hostname`：

```
SELECT
  atimestamp time,
  aint value
FROM table
WHERE $__timeFilter(atimestamp) and hostname in($hostname)
ORDER BY atimestamp
```

 `[[varname]]` 範本變數名為 的範例`hostname`：

```
SELECT
  atimestamp as time,
  aint as value
FROM table
WHERE $__timeFilter(atimestamp) and hostname in([[hostname]])
ORDER BY atimestamp
```

#### 關閉多值變數的引號
<a name="mssql-disabling-quoting-for-multi-value-variables"></a>

 Grafana 會自動為多值變數建立以逗號分隔的引號字串。例如，如果選取 `server02` `server01`和 ，則會格式化為：`'server01', 'server02'`。若要關閉引號，請使用變數的 csv 格式選項。

 `${servers:csv}` 

 如需變數格式化選項的詳細資訊，請參閱 [範本和變數](templates-and-variables.md)。

## 註釋
<a name="mssql-annotations"></a>

 您可以使用註釋在圖形上方覆蓋豐富的事件資訊。您可以透過儀表板功能表/註釋檢視新增註釋查詢。如需詳細資訊，請參閱[註釋](dashboard-annotations.md)。

 **資料欄：**


|  名稱  |  描述  | 
| --- | --- | 
|  time  |  日期/時間欄位的名稱。可以是具有原生 SQL 日期/時間資料類型或 epoch 值的資料欄。 | 
|  timeend  |  結束日期/時間欄位的選用名稱。可以是具有原生 SQL 日期/時間資料類型或 epoch 值的資料欄。 | 
|  text  |  事件描述欄位。 | 
|  tags  |  用於事件標籤的選用欄位名稱，做為逗號分隔字串。 | 

 下列範例程式碼顯示資料庫資料表。

```
CREATE TABLE [events] (
  time_sec bigint,
  description nvarchar(100),
  tags nvarchar(100),
)
```

 我們也使用 中定義的資料庫資料表[時間序列查詢](#mssql-time-series-queries)。

 下列範例程式碼顯示使用具有 epoch 值的時間欄的查詢。

```
SELECT
  time_sec as time,
  description as [text],
  tags
FROM
  [events]
WHERE
  $__unixEpochFilter(time_sec)
ORDER BY 1
```

 下列範例程式碼顯示使用具有 epoch 值的時間和結束時間資料欄的區域查詢。

```
SELECT
  time_sec as time,
  time_end_sec as timeend,
  description as [text],
  tags
FROM
  [events]
WHERE
  $__unixEpochFilter(time_sec)
ORDER BY 1
```

 下列範例程式碼顯示使用原生 SQL 日期/時間資料類型的時間欄的查詢。

```
SELECT
  time,
  measurement as text,
  convert(varchar, valueOne) + ',' + convert(varchar, valueTwo) as tags
FROM
  metric_values
WHERE
  $__timeFilter(time_column)
ORDER BY 1
```

## 預存程序支援
<a name="stored-procedure-support"></a>

 已驗證存放程序是否正常運作。不過，在某些情況下，它可能無法如您預期般運作。應該在資料表、時間序列和註釋查詢中支援存放程序，只要您使用相同的資料欄命名，並以與先前各章節所述的相同格式傳回資料。

 巨集函數無法在預存程序中運作。

### 範例
<a name="mssql-examples"></a>

 對於下列範例，資料庫資料表是在時間序列查詢中定義。假設您想要在圖形面板中視覺化四個序列，例如資料欄 `valueOne`、 `valueTwo`和 的所有組合`measurement`。右側的圖形面板可視覺化我們想要達成的目標。若要解決此問題，您必須使用兩個查詢：

 下列範例程式碼顯示第一個查詢。

```
SELECT
  $__timeGroup(time, '5m') as time,
  measurement + ' - value one' as metric,
  avg(valueOne) as valueOne
FROM
  metric_values
WHERE
  $__timeFilter(time)
GROUP BY
  $__timeGroup(time, '5m'),
  measurement
ORDER BY 1
```

 下列範例程式碼顯示第二個查詢。

```
SELECT
  $__timeGroup(time, '5m') as time,
  measurement + ' - value two' as metric,
  avg(valueTwo) as valueTwo
FROM
  metric_values
GROUP BY
  $__timeGroup(time, '5m'),
  measurement
ORDER BY 1
```

#### 使用 epoch 格式的時間存放程序
<a name="mssql-stored-procedure-using-time-in-epoch-format"></a>

 您可以定義預存程序，以傳回在圖形面板中轉譯四個序列所需的所有資料，例如上述。在此情況下，預存程序接受兩種參數 `@from`和 `int`資料類型`@to`的 ，其應為 epoch 格式的時間範圍 （從-到），用於篩選要從預存程序傳回的資料。

 這會模擬 select `$__timeGroup(time, '5m')`中的 ，並依表達式分組，因此需要許多冗長的表達式。如果需要，您可以將這些擷取到 MSSQL 函數。

```
CREATE PROCEDURE sp_test_epoch(
  @from int,
  @to   int
)   AS
BEGIN
  SELECT
    cast(cast(DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), time))/600 as int)*600 as int) as time,
    measurement + ' - value one' as metric,
    avg(valueOne) as value
  FROM
    metric_values
  WHERE
    time >= DATEADD(s, @from, '1970-01-01') AND time <= DATEADD(s, @to, '1970-01-01')
  GROUP BY
    cast(cast(DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), time))/600 as int)*600 as int),
    measurement
  UNION ALL
  SELECT
    cast(cast(DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), time))/600 as int)*600 as int) as time,
    measurement + ' - value two' as metric,
    avg(valueTwo) as value
  FROM
    metric_values
  WHERE
    time >= DATEADD(s, @from, '1970-01-01') AND time <= DATEADD(s, @to, '1970-01-01')
  GROUP BY
    cast(cast(DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), time))/600 as int)*600 as int),
    measurement
  ORDER BY 1
END
```

 然後，您可以針對圖形面板使用下列查詢。

```
DECLARE
  @from int = $__unixEpochFrom(),
  @to int = $__unixEpochTo()

EXEC dbo.sp_test_epoch @from, @to
```

#### 使用日期時間格式的時間存放程序
<a name="mssql-stored-procedure-using-time-in-datetime-format"></a>

 您可以定義預存程序，以傳回在圖形面板中轉譯四個序列所需的所有資料，例如上述。在此情況下，預存程序接受兩種參數 `@from`和 `datetime`資料類型`@to`的 ，其應為時間範圍 （從-到），將用於篩選要從預存程序傳回的資料。

 這會模擬 select `$__timeGroup(time, '5m')`中的 ，並依表達式分組，因此需要許多冗長的表達式。如果需要，您可以將這些擷取到 MSSQL 函數。

```
CREATE PROCEDURE sp_test_datetime(
  @from datetime,
  @to   datetime
)   AS
BEGIN
  SELECT
    cast(cast(DATEDIFF(second, {d '1970-01-01'}, time)/600 as int)*600 as int) as time,
    measurement + ' - value one' as metric,
    avg(valueOne) as value
  FROM
    metric_values
  WHERE
    time >= @from AND time <= @to
  GROUP BY
    cast(cast(DATEDIFF(second, {d '1970-01-01'}, time)/600 as int)*600 as int),
    measurement
  UNION ALL
  SELECT
    cast(cast(DATEDIFF(second, {d '1970-01-01'}, time)/600 as int)*600 as int) as time,
    measurement + ' - value two' as metric,
    avg(valueTwo) as value
  FROM
    metric_values
  WHERE
    time >= @from AND time <= @to
  GROUP BY
    cast(cast(DATEDIFF(second, {d '1970-01-01'}, time)/600 as int)*600 as int),
    measurement
  ORDER BY 1
END
```

 然後，您可以針對圖形面板使用下列查詢。

```
DECLARE
  @from datetime = $__timeFrom(),
  @to datetime = $__timeTo()

EXEC dbo.sp_test_datetime @from, @to
```

## 提醒
<a name="mssql-alerting"></a>

 時間序列查詢應在提醒條件下運作。警示規則條件中尚不支援資料表格式的查詢。