項目升級-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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...