意义
主要是自己无聊,写一个大家常用到sql自定义函数,练练手。
环境
sql sever数据库,其他数据没试过
思路
把输入值分出两部分:整数+小数(例如:1234566.12元,输出:壹佰贰拾叁万肆仟伍佰陆拾陆元壹角贰分,所以分成两部分处理简单)。
步骤:用Cast()获取整数部分--->ConverToIntRMB()函数处理整数--->ConverToDecimalRMB()函数处理小数
整数部分
创建两张表digits,unit,digits用来存储大写数字;unit用来存储单位:
digits表:
Digit | Chinese |
---|---|
1 | 壹 |
2 | 贰 |
3 | 叁 |
unit表:
UnitPosition | UnitName |
---|---|
1 | ‘’ |
2 | ‘拾’ |
3 | ‘佰’ |
用取余和除数取整调动输入值的位数
input = 123461
digit = input % 10 //获取个位值1
input = input / 10 //移位,input值变为12346
小数部分
其实差不多,digits表一样,unit表变成"角,分",不多解释。
代码部分
CREATE FUNCTION dbo.ConvertToIntRMB(@input DECIMAL(18,2))
RETURNS NVARCHAR(MAX)
AS
BEGIN
--声明三个变量@result:函数返回;@digits:存放映射关系;@unit:存放单位
DECLARE @result NVARCHAR(MAX) = '';
DECLARE @digits TABLE (Digit INT, Chinese NVARCHAR(10));
DECLARE @unit TABLE (UnitPosition INT, UnitName NVARCHAR(10));
DECLARE @unit2 TABLE (UnitPosition INT, UnitName NVARCHAR(10));
--给表插入数据
INSERT INTO @digits (Digit, Chinese)
VALUES
(0, '零'), (1, '壹'), (2, '贰'), (3, '叁'), (4,'肆'), (5, '伍'),(6, '陆'), (7, '柒'), (8, '捌'), (9, '玖');
INSERT INTO @unit (UnitPosition, UnitName)
VALUES
(1, ''), (2, '拾'), (3, '佰'), (4, '仟'), (5, '万'), (6, '拾万'), (7, '佰万'), (8, '仟万'), (9, '亿');
INSERT INTO @unit2 (UnitPosition, UnitName)
VALUES
(1, '分'), (2, '角');
--@position:记录位置用于获取单位
DECLARE @position INT = 1;
--@intNum:整数部分
DECLARE @intNum INT = CAST(@input AS INT);
--@decimalNum:小数部分
DECLARE @decimalNum INT = CAST((@input - @intNum) * 100 AS INT);
--开始逻辑部分
IF @intNum = 0
BEGIN
IF @decimalNum = 0
BEGIN
SET @result = '零元';
END
--只有小数部分
ELSE BEGIN
--小数记录位置用于获取单位
DECLARE @position2 INT = 1;
WHILE @decimalNum > 0
BEGIN
--拿出个位
DECLARE @digit2 INT = @decimalNum % 10;
--小数点左移一位
SET @decimalNum = @decimalNum / 10;
--根据记录位置获取单位
DECLARE @unitName2 NVARCHAR(10) = (SELECT UnitName FROM @unit2 WHERE UnitPosition = @position2);
--小写转换大写
DECLARE @chineseDigit2 NVARCHAR(10) = (SELECT Chinese FROM @digits WHERE Digit = @digit2);
--@position < 3防止跑出去
IF @digit2 > 0 AND @position < 3
BEGIN
SET @result = @chineseDigit2 + @unitName2 + @result;
END
SET @position2 = @position2 + 1;
END
END
END
--整数部分
ELSE BEGIN
--拿出个位,用于决定最后加上元还是元整
DECLARE @firstNum INT = @intNum % 10;
WHILE @IntNum > 0
BEGIN
--拿出个位
DECLARE @digit INT = @intNum % 10;
--整数部分小数点左移一位
SET @intNum = @intNum / 10;
--根据记录位置获取单位
DECLARE @unitName NVARCHAR(10) = (SELECT UnitName FROM @unit WHERE UnitPosition = @position);
--小写转换大写
DECLARE @chineseDigit NVARCHAR(10) = (SELECT Chinese FROM @digits WHERE Digit = @digit);
--给@result赋值
IF @digit > 0
BEGIN
SET @result = @chineseDigit + @unitName + @result;
END
--单位增大
SET @position = @position + 1;
END
--整数部分最后加上元或元整
SET @result = @result + '元';
IF @firstNum = 0 AND @decimalNum = 0
BEGIN
SET @result = @result + '整';
END
END
--小数部分
IF @decimalNum > 0
BEGIN
--小数记录位置用于获取单位
DECLARE @position3 INT = 1;
--记录小数
DECLARE @decimalResult NVARCHAR(500)= '';
WHILE @decimalNum > 0
BEGIN
--拿出个位
DECLARE @digit3 INT = @decimalNum % 10;
--小数点左移一位
SET @decimalNum = @decimalNum / 10;
--根据记录位置获取单位
DECLARE @unitName3 NVARCHAR(10) = (SELECT UnitName FROM @unit2 WHERE UnitPosition = @position3);
--小写转换大写
DECLARE @chineseDigit3 NVARCHAR(10) = (SELECT Chinese FROM @digits WHERE Digit = @digit3);
--@position3 < 3防止跑出去
IF @digit3 > 0 AND @position3 < 3
BEGIN
SET @decimalResult = @chineseDigit3 + @unitName3 + @decimalResult;
END
SET @position3 = @position3 + 1;
END
SET @result = @result + @decimalResult;
END
RETURN @result;
END;
代码大概如此没有过多优化,小数处理部分代码重复,就这样吧。
后记
纯text手工打,懒得上sql sever,可能有bug,思路就是:0一种情况,纯整数一种情况,纯小数一种情况,整数和小数混杂一种情况,中间忘记个位为零时候单位是“元整”而非“元”。
优化思路:整数一个函数,小数一个函数,在整数函数中调用小数函数,解决代码重复问题,同时还能提高效率。
下次见!