SQL Server 字段類型 decimal(18,6)小數點前是幾位?
不可否認,這是一個很低級的問題....
為什么會問這么低級的問題?
由於這個問題,導致一個數據導入的SP執行失敗....以至於困擾了我好幾個小時....
事情是這樣的...
公司總部上了一套Oracle的ERP,我們系統中有些數據要從里面取,比如Supplier,Product等。
Oracle會導出數據文件,我們同SSIS刷到本地相應的數據庫(數據庫的字段和Oracle的一致)。
對我們來說就是數據源變了,需要把Oracle的數據轉化成我們先系統可以用的數據。
由於Oracle上線比較"快",為了讓現有的系統基本能跑起來,同事寫一個SP轉化導入到我們系統的數據庫。
這個SP 寫的比較粗糙。
同事只是把Oracle的數據在進行處理之后 AS成現系統的字段。
sql語句是這樣的:
SELECT [DT_UAMT],[DT_DAMT],[DT_AMT] INTO Temp_DT_PODT FROM ( NULL AS DT_UAMT ,convert(varchar,convert(decimal(18,6),isnull(usd_amount,'0') * 100)) as DT_DAMT ,convert(varchar,convert(decimal(18,6),isnull(LINE_AMOUNT,'0') * 100)) as DT_AMT FROM OracleDB.[dbo].OracleTB
)
當然了 字段不止這三個,一個表有將近100個字段,這里只是舉例說明問題。
同事這里用到了SELECT INTO語句。
SQL SELECT INTO 語句可用於創建表的備份復件。
這樣寫可以快速達到效果不用一個一個表去建並且保證數據可以完全導出過來。
但是這樣寫會有問題,
1、首先SELECT INTO需要into的這個表不存在,所以每次都需要把Temp_DT_PODT給Drop掉。 2、由於Oracle的字段類型和我們的不一樣,會導致創建出來的字段類型和我們原數據庫的類型不一樣。 3、當用 null as成一個字段的時候,into的表中對應字段類型為int
上述第三條會導致有些之前SP會報錯....
你可能會說不用NULL as DT_UAMT用 '' as DT_UAMT。當然是可以的。
我也說過 這個SP是為了之前的系統能夠跑起來寫的,有些問題存在是正常的.....
然后解決這些問題就交給了我.....(我好苦逼,哭暈在廁所....)
畢竟SELECT INTO 語句可用於創建表的備份復件的,我們刷數據還是用insert into的好。
insert into 是需要表的。一個表將近100個字段...一共10幾個表.....手動建肯定不可能了
我是這樣想的。
之前SP中into的表只是字段數據類型不對,名稱都是對的。我只需要把原來的表的字段類型修改對了就行了。
恩,忽然感覺工作量小了很多有沒有,哈哈。
我通過數據庫 任務->執行腳本 把原SP into的表的結構導出來。
再把原系統用的表結構導出來。
對比兩個文件把相應的字段類型改一下。
並記錄下修改的字段,寫出相應的SQL 語句進行修改。
我在測試數據庫中 建了一個測試數據庫test
把SP into的表通過導出文件建好。
讓執行我整理的SQL 語句。
哈哈,我的工作是不是做完了?
明顯沒有....在我修改原來的SP 將select into 改成insert into 並執行的時候.....
竟然報錯了....
SQL Server報告出錯:“將數據類型 varchar 轉換為 numeric 時出錯。”
我靠,這是什么情況?
我改了很多decimal的...難道我一個一個去試試....
我還真一個一個去試了試。結果發現時DT_DAMT這個字段出錯了。
難道是數據問題?數據中有不是數字的數據?
select DT_DAMT from OracleDB.[dbo].OracleTB where isnumeric(DT_DAMT )!=1
結果返回為空....
我去,都是數字啊。
這是什么情況?
難道長度超出了?
應該不會啊,我建的表中DT_DAMT字段是 decimal(18,6)類型。
並且同事寫的SP中也是轉化成了 decimal(18,6)
convert(varchar,convert(decimal(18,6),isnull(usd_amount,'0') * 100)) as DT_DAMT
(額。。。貌似還乘以了100.當時沒注意到)
我看了一下原SP into表的DT_DAMT類型decimal(18,2)
我靠 decimal(18,2)可以,我的decimal(18,6)就不行?
不過也沒影響吧,都是decimal(18,*)的類型,小數點前面應該都是18位。
我之前真的是這么以為的。
於是我在執行了一下sql語句。
Select convert(decimal(18,2),isnull(LINE_AMOUNT,'0') ) as DT_DAMT FROM OracleDB.[dbo].OracleTB
沒報錯....
Select convert(decimal(18,6),isnull(LINE_AMOUNT,'0') ) as DT_DAMT FROM OracleDB.[dbo].OracleTB
竟然報錯了
SQL Server報告出錯:“將數據類型 varchar 轉換為 numeric 時出錯。”
於是我果斷百度一下 Decimal
Decimal 數據類型 介紹
Decimal為SQL Server、MySql等數據庫的一種數據類型,不屬於浮點數類型,可以在定義時划定整數部份以及小數部分的位數。使用精確小數類型不僅能夠保證數據計算更為精確,還可以節省儲存空間,例如百分比使用decimal(4,2)即可。存儲數據范圍是:-10^38~10^38-1 的固定精度和小數位的數字。一個decimal類型的數據占用了2~17個字節。 decimal[ (p[ , s] )] p (有效位數) 可儲存的最大十進位數總數,小數點左右兩側都包括在內。有效位數必須是 1 至最大有效位數 38 之間的值。預設有效位數是 18。 s (小數位數) 小數點右側所能儲存的最大十進位數。小數位數必須是從 0 到 p 的值。只有在指定了有效位數時,才能指定小數位數。預設小數位數是 0;因此,0 <= s <= p。最大儲存體大小會隨著有效位數而不同。 Decimal(p,s)表示數值中共有n位數,其中整數p-s位,小數s位。例:decimal(10,6),數值中共有10位數,其中整數占4位,小數占6位。
decimal(10,6),數值中共有10位數,其中整數占4位,小數占6位。
ISNUMERIC 介紹
語法 ISNUMERIC ( expression ) 參數 expression 要計算的表達式。 返回類型 int 注釋 當輸入表達式得數為一個有效的整數、浮點數、money 或 decimal 類型,那么 ISNUMERIC 返回 1;否則返回 0。返回值為 1 確保可以將 expression 轉換為上述數字類型中的一種。