---
# System prepended metadata

title: 常用MSSQL指令
tags: [MSSQL]

---

###### tags: `MSSQL`
# 常用MSSQL指令
最近修改日期:20201019
<style>
.blue {
  color: blue;
}
.red {
  color: red;
}
</style>

### 比對兩個相同的資料表
20201019
```sql=
select * from TEST1
EXCEPT
select * from TEST2
--由左側的輸入查詢資料，傳回不同的資料列(找相異資料)
```

```sql=
select * from TEST1
INTERSECT
select * from TEST2
--由左側及右側的輸入查詢資料，傳回相同的資料列(找相同資料)
```
EXCEPT 會從左側查詢中傳回在右側查詢中找不到的任何個別值。
INTERSECT 會傳回 INTERSECT 運算元左右兩側查詢都傳回的任何個別值。
使用 EXCEPT 或 INTERSECT 的兩個查詢，其結果集的基本組合規則如下：
在所有查詢中，資料行的數目和順序都必須相同。

參考:[SQL SERVER 比對兩個資料表差異 EXCEPT ; INTERSECT](https://iamtaco.pixnet.net/blog/post/45199193)

---
### 欄位自動編號
20200930
資料表建立後，尚無資料前，使用
 alter table TableName drop column AutoCounter 
 alter table TableName add AutoCounter int identity(1,1)
 方法設定之
說明:標識列， identity(a,b)，ab均為正整數，a表示開始數，b表示增幅，就像identity(1,1)意思就是該列自動增長，由1開始每次增加是1

---
 
### 查詢DB中所有table的資料筆數
20200928
```sql=
SELECT S.NAME '結構描述', O.NAME '資料表名稱', P.ROWS '列總數'
FROM SYS.OBJECTS O INNER JOIN SYS.SCHEMAS S
ON O.SCHEMA_ID = S.SCHEMA_ID
INNER JOIN SYS.PARTITIONS P
ON O.OBJECT_ID = P.OBJECT_ID
WHERE (O.TYPE = 'U') AND
(P.INDEX_ID IN (0,1))
ORDER BY S.NAME, O.NAME ASC;
```
參考:[阿輝的零碎筆記](https://dotblogs.com.tw/grayyin/2017/04/28/231156)

---

### 排名函數 ROW_NUMBER、RANK、DENSE_RAN、NTILE 語法
是Sql Server2005新增的功能。
20200707

**ROW_NUMBER用法**: 依照指定的欄位排序，並逐筆加上順號的方式。
(Oracle也可以用，但是效能似乎不好:需再確認)


```sql
SELECT 
   ROW_NUMBER() OVER(ORDER BY AccountID) AS Account_OrderID
	,*
FROM MEMBERS
```

**RANK用法:** 依照排序的欄位，相同的資料相同排名，下一個不同會【跳脫】
```sql
SELECT 
 RANK() OVER(ORDER BY CustomerID) AS ROWID
,*
FROM Orders
```

**DENSE_RANK用法:** 依照排序的欄位，相同的資料相同排名，下一個不同會【不跳脫】
```sql
SELECT 
 DENSE_RANK() OVER(ORDER BY CustomerID) AS ROWID
 ,*
FROM Orders
```

**NTILE用法**:可以對序號進行分組處理，將有序分區中的行分發到指定數目的組中
```sql
select NTILE( 4 ) OVER ( order  by  [ SubTime ]  desc ) as ntile, *  from  [ Order ]
```

參考:
1.[[SQL]為查詢的結果加上序號(ROW_NUMBER,RANK,OVER)](https://dotblogs.com.tw/topcat/2009/08/06/9906)
2.[Sql 四大排名函数（ROW_NUMBER、RANK、DENSE_RANK、NTILE）简介](https://www.cnblogs.com/52xf/p/4209211.html)
3.[關於OVER子句的使用方式](https://ithelp.ithome.com.tw/articles/10190257) 有Partition By語法。

---
### INSERT 語法:MSSQL Insert 語法 
20200703 M20200710
語法:
```sq    
INSERT INTO table_name
VALUES (value1_1, value2_2, value3_3,···),
(value2_1, value2_2, value2_3,···),
(value3_1, value3_2, value3_3,···),
······;

INSERT INTO table_name (column1, column2, column3,...)
SELECT othercolumn1, othercolumn2, othercolumn3,...
FROM othertable_name;

INSERT INTO table_name (欄位要列出來，用* 不行)
SELECT *
FROM othertable_name;
```
由舊資料表建立一模一樣新資料表方法
```sql
SELECT * INTO DB1.DBO.MyTABLE FROM DB2.DBO.MyTABLE WHERE 1=2  --若去除 WHERE 1=2，則連資料會一起進去。
```
與Oracle 語法:INSERT INTO TABLENAME VALUE (SELECT* FROM TABLENAME@DB2 WHERE 1=1) 有差異。

---
### 跨伺服器建立Table(View)方法 
20200629 20201019

<font class='blue'>USE</font> Local_DB
<font class='blue'>EXEC</font> sp_addlinkedserver @server = '192.168.100.200', @srvproduct = N'SQL Server'
<font class='blue'>EXEC</font> sp_addlinkedsrvlogin @rmtsrvname = '192.168.100.200' , @useself = false, @rmtuser = 'remote_db_account', @rmtpassword = 'remote_db_password'
利用 sp_addlinkedserver 跟遠端資料庫SQL建立關連
利用 sp_addlinkedsrvlogin 設定登入遠端資料庫的帳號、密碼等訊息
Local_DB 換成你程式中原本使用的資料庫名稱
192.168.100.200 當然要換成你遠端伺服器主機的IP
rmtuser 換成遠端資料庫可登入SQL的帳號
rmtpasswword 換成遠端資料庫可登入SQL帳號的 密碼
```sql
CREATE VIEW Remote_view1
AS
SELECT *
FROM [192.168.100.200].Remote_DB.dbo.Remote_Table
```
嚴格的來說 SELECT statement格式為
```sql 
SELECT * FROM [IP 或 Server_name].Remote_DB_name.DB_Owner_name.Remote_Table_Name
```
刪除用EXEC sp_addlinkedsrvlogin ...方法建立的連線(因為密碼書錯之故)。方法如下:
```sql 
EXEC sp_droplinkedsrvlogin @rmtsrvname = '192.168.100.200',@locallogin = 'sa' 
```

Ref:[SQL 建立遠端資料庫資料表到本地 Table 或 VIEW](https://blog.xuite.net/tolarku/blog/21137675-SQL+%E5%BB%BA%E7%AB%8B%E9%81%A0%E7%AB%AF%E8%B3%87%E6%96%99%E5%BA%AB%E8%B3%87%E6%96%99%E8%A1%A8%E5%88%B0%E6%9C%AC%E5%9C%B0+Table+%E6%88%96+VIEW)
參考:[sp_addlinkedsrvlogin 、 sp_droplinkedsrvlogin 使用方法](https://tsuozoe.pixnet.net/blog/post/22419129)

---
### 跨伺服器查詢 
20200623
也可以操作insert 語法

```SQL
SELECT T.*
FROM OPENROWSET('MSDASQL',
'DRIVER={SQL Server};
SERVER=192.168.0.100;
UID=sa;
PWD=ncunicom_alarm',
BSC_ALARM.dbo.ALARM_LIST) AS T
/* 其中，192.168.0.100為遠端伺服器IP，也可以使用別名，
BSC_ALARM是遠端資料庫，
ALARM_LIST遠端資料庫中的資料表
*/
```
若出現==連結伺服器 "(null)" 的 OLE DB 提供者 "MSDASQL" 並未包含資料表 ""BSC_ALARM.dbo.ALARM_LIS""。該資料表不存在，或是目前的使用者沒有使用該資料表的權限。== 的錯誤。
<font class='blue'>則要開啟 開放 'd Hoc Distributed Queries 的使用權限，開啟資料庫 - Facet</font>
語法如下:
```SQL
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'ad hoc distributed queries', 1;
GO
RECONFIGURE;
GO
```
Ref:[MS SQLSERVER如何實現跨伺服器查詢](https://www.itread01.com/content/1547635336.html)
Ref:[SQL使用OPENROWSET出現訊息 SQL Server 已封鎖元件 'Ad Hoc Distributed Queries' 的 STATEMENT 'OpenRowset/OpenDatasource' 之存取](https://dotblogs.com.tw/atalin/2010/11/18/19531)

---
### CREATE TABLE 建立資料表方法 
20200622
由另外的MS資料庫，建立一模一樣的資料表到新的MS資料庫。
WHERE 1=2 不複製資料過去。(若要連資料一起過去，可用1=1或是移除 WHERE 1=2)
```SQL
SELECT * INTO NEWDB.DBO.DEPT FROM OLDDB.DBO.DEPT WHERE 1=2
```
註:與Oracle 用CREATE TABLE ..的手法不同，特別紀錄一下。

---

S20200622 By YTC
M20200623 ,M20200629 ,M20200703 
M20200707 調正順序，新的在上面。並加入MSSQL 較特別的ROW_NUMBER、RANK 等語法。
M20200710
M20200928 加入查詢DB中所有table的資料筆數語法
M20200929
M20201019 加入資料表比對查詢,加入[跨伺服器建立Table(View)方法] 之刪除錯誤資料