I'm having issues executing a stored procedure. Basically, when I execute my stored procedure by itself, it works just fine, and returns the correct values. However, when I call the same stored procedure with a parameter and try to assign return value into a variable it doesn't return the correct value always return 0. Is there something weird going on with how the variables are handled? Or is something else going wrong? See my code below.
ALTER PROCEDURE [dbo].[NumbersToWords]
@Number INT
AS
BEGIN
SET NOCOUNT ON;
SET @Number = ABS(@Number)
DECLARE @vResult NVARCHAR(MAX) = ''
-- pre-data
DECLARE @tDict TABLE (Num INT NOT NULL, Nam NVARCHAR(255) NOT NULL)
INSERT
INTO @tDict (Num, Nam)
VALUES (1,'one'),(2,'two'),(3,'three'),(4,'four'),(5,'five'),(6,'six'),(7,'seven'),(8,'eight'),(9,'nine'),
(10,'ten'),(11,'eleven'),(12,'twelve'),(13,'thirteen'),(14,'fourteen'),(15,'fifteen'),(16,'sixteen'),(17,'seventeen'),(18,'eighteen'),(19,'nineteen'),
(20,'twenty'),(30,'thirty'),(40,'fourty'),(50,'fifty'),(60,'sixty'),(70,'seventy'),(80,'eighty'),(90,'ninety')
DECLARE @ZeroWord NVARCHAR(10) = 'zero'
DECLARE @DotWord NVARCHAR(10) = 'point'
DECLARE @AndWord NVARCHAR(10) = 'and'
DECLARE @HundredWord NVARCHAR(10) = 'hundred'
DECLARE @ThousandWord NVARCHAR(10) = 'thousand'
DECLARE @MillionWord NVARCHAR(10) = 'million'
DECLARE @BillionWord NVARCHAR(10) = 'billion'
DECLARE @TrillionWord NVARCHAR(10) = 'trillion'
-- decimal number
DECLARE @vDecimalNum INT = (@Number - FLOOR(@Number)) * 100
DECLARE @vLoop SMALLINT = CONVERT(SMALLINT, SQL_VARIANT_PROPERTY(@Number, 'Scale'))
DECLARE @vSubDecimalResult NVARCHAR(MAX) = N''
IF @vDecimalNum > 0
BEGIN
WHILE @vLoop > 0
BEGIN
IF @vDecimalNum % 10 = 0
SET @vSubDecimalResult = FORMATMESSAGE('%s %s', @ZeroWord, @vSubDecimalResult)
ELSE
SELECT @vSubDecimalResult = FORMATMESSAGE('%s %s', Nam, @vSubDecimalResult)
FROM @tDict
WHERE Num = @vDecimalNum%10
SET @vDecimalNum = FLOOR(@vDecimalNum/10)
SET @vLoop = @vLoop - 1
END
END
-- main number
SET @Number = FLOOR(@Number)
IF @Number = 0
SET @vResult = @ZeroWord
ELSE
BEGIN
DECLARE @vSubResult NVARCHAR(MAX) = ''
DECLARE @v000Num DECIMAL(15,0) = 0
DECLARE @v00Num DECIMAL(15,0) = 0
DECLARE @v0Num DECIMAL(15,0) = 0
DECLARE @vIndex SMALLINT = 0
WHILE @Number > 0
BEGIN
-- from right to left: take first 000
SET @v000Num = @Number % 1000
SET @v00Num = @v000Num % 100
SET @v0Num = @v00Num % 10
IF @v000Num = 0
BEGIN
SET @vSubResult = ''
END
ELSE
BEGIN
--00
IF @v00Num < 20
BEGIN
-- less than 20
SELECT @vSubResult = Nam FROM @tDict WHERE Num = @v00Num
IF @v00Num < 10 AND @v00Num > 0 AND (@v000Num > 99 OR FLOOR(@Number / 1000) > 0)--e.g 1 001: 1000 AND 1; or 201 000: (200 AND 1) 000
SET @vSubResult = FORMATMESSAGE('%s %s', @AndWord, @vSubResult)
END
ELSE
BEGIN
-- greater than or equal 20
SELECT @vSubResult = Nam FROM @tDict WHERE Num = @v0Num
SET @v00Num = FLOOR(@v00Num/10)*10
SELECT @vSubResult = FORMATMESSAGE('%s %s', Nam, @vSubResult) FROM @tDict WHERE Num = @v00Num
END
--000
IF @v000Num > 99
SELECT @vSubResult = FORMATMESSAGE('%s %s %s', Nam, @HundredWord, @vSubResult) FROM @tDict WHERE Num = CONVERT(INT,@v000Num / 100)
END
--000xxx
IF @vSubResult <> ''
BEGIN
SET @vSubResult = FORMATMESSAGE('%s %s', @vSubResult, CASE
WHEN @vIndex=1 THEN @ThousandWord
WHEN @vIndex=2 THEN @MillionWord
WHEN @vIndex=3 THEN @BillionWord
WHEN @vIndex=4 THEN @TrillionWord
WHEN @vIndex>3 AND @vIndex%3=2 THEN @MillionWord + ' ' + RTRIM(LTRIM(REPLICATE(@BillionWord + ' ',@vIndex%3)))
WHEN @vIndex>3 AND @vIndex%3=0 THEN RTRIM(LTRIM(REPLICATE(@BillionWord + ' ',@vIndex%3)))
ELSE ''
END)
SET @vResult = FORMATMESSAGE('%s %s', @vSubResult, @vResult)
END
-- next 000 (to left)
SET @vIndex = @vIndex + 1
SET @Number = FLOOR(@Number / 1000)
END
END--ok
SET @vResult = FORMATMESSAGE('%s %s', RTRIM(LTRIM(@vResult)), COALESCE(@DotWord + ' ' + NULLIF(@vSubDecimalResult,''), ''))
-- result
SELECT UPPER(@vResult) AS 'Result'
END
This SQL query perfect
declare @number INT = 1520123
exec spWebNumbersToWords @number = 1520123
But when I try to run this SQL
declare @number INT = 1520123
declare @str nvarchar(max)
exec @str = NumbersToWords @number = 1520123
select @str as 'Word'
return 0 for @str
What am I missing here?
1条答案
按热度按时间fkvaft9z1#
You're confusing a select inside a procedure with a return statement. They don't do the same thing.
A select just outputs data normally. A RETURN(0) returns an exit code which you read when you do: exec @str = numbers... Since a procedure can only return INT, you cannot really return your strings this way. Usually what you do is add another parameter with an output where you put your return, something like:
And then you can call your procedure this way: