項目升級-oracle改版sql server問題點彙總

来源:https://www.cnblogs.com/zhangdk/archive/2019/02/26/oracle_sqlserver.html
-Advertisement-
Play Games

最近項目升級,需要把原來的oracle版本改為sql server版本。由於項目的分層設計,主要的修改內容也就是存儲過程,sql語句。如今改的七七八八,整理一下踩過的坑,備忘! ...


目錄

最近項目升級,需要把原來的oracle版本改為sql server版本。由於項目的分層設計,主要的修改內容也就是存儲過程,sql語句。如今改的七七八八,整理一下踩過的坑,備忘!

1.符號使用

1.1 :->@

帶參數的sql語句,oracle的參數標識使用首碼":",sql server首碼"@"。

  • oracle版
SELECT * FROM table1 WHERE column1=:column1
  • sql server版
SELECT * FROM table1 WHERE column1=@column1

帶參數的sql語句,在代碼中添加參數時,oracle同一個參數可以添加多次,sql server添加多次會報異常。

  • oracle版本
...
db.AddInParameter(cmd, "column1", DbType.String,column1);
db.AddInParameter(cmd, "column2", DbType.String,column2);
...
db.AddInParameter(cmd, "column1", DbType.String,column1);
...

oracle可以像上面這樣,再次添加同名的參數,但是連接sql server資料庫時不允許。

1.2 mod()->%

求餘運算

1.3 ||->+

字元串連接符

oracle的||專門用來做字元串拼接,因此類似下麵這樣的字元串和數字的拼接是可以成功的:

select 'abc'||123 from dual

但是在sql server中類似下麵的字元串和數字拼接是無法直接進行的:

select 'abc'+123

sql server傾向於將字元串轉為數字,因此報異常。如果要實現字元串拼接的效果,需要做數據類型轉換

select 'abc'+convert(varchar(10),123)

這種情況在存儲過程等複雜的操作中,做動態sql拼接時,最容易忽略。

1.4 off等表別名

oracle中的表別名off在sql server中是關鍵字,導致sql語句錯誤。因此,在使用表別名的時候我們還是儘量避免掉這種類似關鍵字的命名。

1.5 columnnum=1->top 1

oracle在排序時,可以使用columnnum=1獲取第一條記錄,sql server排序時可以使用top 1來獲取。

1.6 minus->except

oracle的minus對應sql server的except,直接替換

1.7 number->decimal

oracle中的number類型,即使設置了小數位數,比如decimal(18,2),但是資料庫不會對插入的數值補零,插入整數就是整數。但是sql server中會根據設置的數據類型,在數字末尾補零以補足小數位。這個差異會影響前端數字的格式化展示。

1.8 date -> datetime

oracle中date數據類型包括日期和時間兩部分。

sql server中date只包括日期部分,datetime包括日期和時間兩部分,timestamp遞增數字,與時間無關。

oracle中timestamp也包括日期和時間兩部分,與date的區別主要是相減時,timestamp相減結果單位是秒,date相減結果是天。兩個類型可以相互轉換。

C#中向sql server中插入日期類型時,C#預設日期是01/01/01 00:00:00,直接插入資料庫會導致數據一齣,因為C#向sql server中插入datetime數值類型時(DbType.SqlDateTime),有效日期範圍為1/1/1753 12:00:00 ~ 12/31/9999 11:59:59 PM。資料庫直接導入日期欄位,或者直接修改資料庫時,是可以設置為 1/1/1 00:00:00的。

2.函數轉換

2.1 nvl->isnull

這兩個函數完全等價,可以直接替換使用。

2.2 substr->substring

substr(str,startIndex,[length]) oracle中length參數可以省略,預設取到結尾;
substring(str,startIndex,length) sql server中length參數不能省略。
因此做替換時,要根據業務確定截取長度。

2.3 decode->case when end

oracle中的decode函數使用case when end語句替換,對於嵌套的decode函數我們可以通過組合when的邏輯表達式實現。

  • oracle版
select decode(column1,0,'狀態1',1,'狀態2','其他') from table1;

select decode(column1,0,decode(column2,0,'狀態1','狀態2'),'其他') from table1;
  • sql server版
select case column1
        when 0 then '狀態1'
        when 1 then '狀態2'
        else '其他' end
    from table1;
    
select case 
        when column1 = 0 and column2 = 0 then '狀態1'
        when column1 = 0 then '狀態2'
        else '其他' end
    from table1;

2.4 數據類型轉換

  • to_number(str)->convert(int,str)
  • to_char(str)->convert(nvarchar(n),str)
  • to_char(date,'yyyy-MM-dd')->convert(varchar(100),date,23)
  • to_char(date,'yyyy-MM-dd hh24@mi@ss')->convert(varchar(100),date,20)
  • to_char(date,'yyyyMMdd')->convert(varchar(100),date,112)

2.5 sq_executesql第一個參數必須是nvarchar類型

2.6 instr -> charindex

兩個函數的實現功能一樣,但是參數順序卻不同,一定要註意。

oracle版本

select instr('abcde','c') from dual

sql server版本

select charindex('c','abcde')

2.7 分組併合併列

原始數據結構
學號 | 名字 | 愛好
---|---|---
201012 | 張三 | 籃球
201012 | 張三 | 乒乓球
201013 | 李四 | 唱歌
201012 | 張三 | 羽毛球
201013 | 李四 | 羽毛球
201013 | 李四 | 繪畫

目標視圖
學號 | 名字 | 愛好
---|---|---
201012 | 張三 | 籃球,乒乓球,羽毛球
201013 | 李四 | 唱歌,羽毛球,繪畫

oracle 11g

select 學號,名字,listagg(愛好,',') within group(order by 愛好) from table1 group by 學號,名字

oracle 其他版本

select 學號,名字,wm_concat(愛好) from table1 group by 學號,名字

sql server

select 學號,名字,
stuff((select ','+愛好 from table1 for xml path('')),1,1,'') 愛好
from table1
group by 學號,名字

3. 語法規則

3.1 子查詢別名

oracle中子查詢作為from中查詢目標可以不使用別名,但是sql server中必須命名別名。

oracle版本

select column1,column2,column3,column4
from (select column1,column2,column3,column4 from table1);

sql server版本

select column1,column2,column3,column4
from (select column1,column2,column3,column4 from table1) a;

3.2 sql server樹形查詢

with定義的sql片段作為查詢對象,實現樹形查詢。

with cte(id,parentId,column1,column2,column3) as
(
    select column1,column2,column3 from table1
    --這裡可以接收查詢參數
    --where column1 = ''
    union all
    select column1,column2,column3 from table1 inner join cte t1 
    on t1.id = t2.parentId --自下而上查詢
    --on t1.parentId = t2.id --自上而下查詢
)

select * from cte;

3.3 sql server 使用merge info

項目中作為更新或插入場景使用。

merge into table1 t1
using (select @id id,@para1 column1,@para2 column2,@para3 column3) t2
on t1.id = t2.id
when matched then
update set t1.column1 = t2.column1,t1.column2 = t2.column2,t1.column3 = t2.column3
when not matched then
insert(id,column1,column2,column3) values(t2.column1,t2.column2,t2.column3)

其中oracle在一些沒有from目標的操作時,使用dual作為操作目標。sql server在這種情況下,直接不寫from部分即可。

3.4 inserted表與deleted表

The deleted table stores copies of the affected rows during DELETE and UPDATE statements. During the execution of a DELETE or UPDATE statement, rows are deleted from the trigger table and transferred to the deleted table. The deleted table and the trigger table ordinarily have no rows in common.

deleted表存儲受Delete和Update語句操作影響的行的副本。執行delete或update語句期間,受影響的行從觸發器所在表轉移到deleted表。deleted表和觸發器所在表通常沒有共同的行。

The inserted table stores copies of the affected rows during INSERT and UPDATE statements. During an insert or update transaction, new rows are added to both the inserted table and the trigger table. The rows in the inserted table are copies of the new rows in the trigger table.

inserted表存儲受insert和update語句操作影響的行的副本。執行insert或update事務時,新行被添加到inserted表和觸發器所在表。inserted表中的行是觸發器所在表新行的副本。

An update transaction is similar to a delete operation followed by an insert operation; the old rows are copied to the deleted table first, and then the new rows are copied to the trigger table and to the inserted table.

一個update事務類似於一個delete操作後跟一個insert操作。舊行先拷貝到deleted表,然後新行拷貝到觸發器所在表和inserted表。

Use the inserted and deleted Tables

3.5 insert\update\delete中使用output

利用inserted表和deleted表,輸出插入後自動生成的id等欄位,避免insert後,在執行select查詢的繁瑣。

insert into table1(column1,column2,column3)
output inserted.id,inserted.time into @para1,@para2
values(@column1,@column2,@column3)

3.6 sql語句或存儲過程資料庫執行很快,程式中執行很慢

3.6.1 程式傳遞參數類型與資料庫不一致

...
db.AddInParameter(cmd, "column1", DbType.Decimal,column1);
db.AddInParameter(cmd, "column2", DbType.String,column2);
db.AddInParameter(cmd, "column3", DbType.String,column3);
...

這裡的DbType指定的類型一定要與資料庫的數據類型保持一致,否則在執行大量數據查詢時,會存在數據類型轉換,嚴重影響sql語句執行效率。其中比較以忽略的類型

varchar -> DbType.AnsiString
nvarchar -> DbType.String

這一對是比較容易不一致的,我們一般給varchar欄位和nvarchar欄位都傳遞的DbType.String。這樣在數據量小時沒有問題,數據量大時會非常慢。

3.6.2 存儲過程執行計划過期

由於存儲過程是預編譯的,在第一次執行的時候,會生成執行計劃,以後執行的時候,會使用這個執行計劃(除非顯示指定重新編譯),而不是每次執行時都生成執行計劃。當存儲過程涉及的對象結構調整,或者相關的數據產生了很大的變化,這可能導致原來的計劃不適合當前的現狀(執行計划過期),這種情況下應該重新編譯存儲過程。

exec sp_recompile @objname='存儲過程名'

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一:實驗環境 虛擬機:win7,winserver 2008 二:實驗過程 (1)在server創建用戶 (2)將win7加入到域st13.com中 首先修改win7的dns伺服器地址為伺服器server2008的地址 接下來進行連通性測試: Server ping win7 Win7 ping s ...
  • Fixed-Point Designer™ 提供開發定點和單精度演算法所需的數據類型和工具,以在嵌入式硬體上進行性能優化。Fixed-Point Designer 會分析您的設計並提供建議的數據類型和屬性,例如字長和定標。您可以指定詳細的數據屬性,如舍入模式和溢出操作,以及混合單精度和定點數據。您可以 ...
  • win7下建立超級隱藏賬戶 實驗目的: 隱藏用戶,不讓管理員簡單的發現 隱藏方法: 1.命令提示符中創建隱藏賬戶這種方法只能將賬戶在"命令提示符"中進行隱藏,而對於"電腦管理"則無能為力。因此這種隱藏賬戶的方法並不是很實用,只對那些粗心的管理員有效,是一種入門級的系統賬戶隱藏技術 2. 註冊表隱藏 ...
  • --crontab檢查是否安裝[oracle@rac1 ~]$ rpm -qa | grep crontabcrontabs-1.10-8啟動與關閉[oracle@rac1 ~]$ /etc/init.d/crond stop/start/restart/reload全局配置文件[root@rac1 ...
  • 1.運行 gpedit.msc →computer configuration→administrative templates→windows componets→Remote Desktop→Remote Desktop session host→Connections→Limit number ...
  • 在Linux系統下,有七類文件類型: 普通文件( ) 目錄(d) 軟鏈接(字元鏈接L) 套接字文件(S) 字元設備(S) 塊設備(B) 管道文件(命名管道P) 普通文件、目錄、軟鏈接無需多解釋。 管道文件 管道分為 匿名管道和命名管道 。管道都是一端寫入、另一端讀取,它們是單方向數據傳輸的,它們的數 ...
  • 首先添加php官方源 $ sudo add-apt-repository ppa:ondrej/php 然後更新源 $ sudo apt-get update 然後安裝 $ sudo apt-get install php7.0 php7.0-cli php7.0-fpm php7.0-gd php ...
  • 轉自:http://www.maomao365.com/?p=8102 摘要: 下文講述向已存在表上添加新欄位及欄位備註的方法,如下所示: 實驗環境:sql server 2008 R2 1. 添加新欄位及欄位備註的語法USE 資料庫名ALTER TABLE 表名 ADD 欄位名 類型 預設值 是否 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...