###### 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)方法] 之刪除錯誤資料