我如何让select下面的字符串变成returns3? SELECT '1+2'

How do I select the following string so it returns 3? SELECT '1+2'

在 table 的第 "SumStrings" 列中,我有诸如“1+2”或“1+2-3”之类的字符串,如下所示:

SumStrings
1+2
1+2-3

换句话说:

DROP TABLE IF EXISTS #theSums;
CREATE TABLE #theSums (SumStrings VARCHAR(25))
INSERT INTO #theSums
    values
        ('1+2'),
        ('1+2-3');

我如何 select 从这个 table 中得到这些总和的结果?也就是说,如果只有上述两个字符串在 table 中,那么 selection 的结果应该是 3 和 0

这个问题String Expression to be evaluated to number主要是针对函数的创建我想要一个简单的脚本,select来自table

您将必须查询字符串并在执行查询的程序中评估它们。这很重要,但有许多用 flex+bison(或其他工具)编写的语言示例,如果您真的、真的必须存储表达式而不是它们的值,它们将帮助您评估表达式。

这是使用 dynamic sql

的一种方法
DECLARE @sql VARCHAR(8000) 

SELECT @sql = Stuff((SELECT 'union all select ' + sumstrings 
                     FROM   #thesums 
                     FOR xml path('')), 1, 9, '') 

PRINT @sql 

EXEC (@sql) 

这里不容易...您可以使用动态创建的语句:

Prdp 的回答很好,只是针对 SQL-injection

的补充

您可以使用 XML 的隐式功能来计算 a - 这就是回退! - 文字 值。没有办法绕过动态 SQL,但这将有助于防止疯狂的值:

试试这个

SELECT CAST('' AS XML).value('1+2','int') AS Result;

这个例子有 CURSOR,但同样可以用@Prdp 的方法来完成:

CREATE TABLE YourTable(ComputeString VARCHAR(100));
INSERT INTO YourTable VALUES('1+2'),('-2+3'),('3*(4+5)'),('12/4');

DECLARE @cs VARCHAR(100);

DECLARE c CURSOR FOR SELECT 'SELECT CAST('''' AS XML).value(''' +  REPLACE(ComputeString,'/',' div ') + ''',''int'') AS Result;' FROM YourTable
OPEN c;
FETCH NEXT FROM c INTO @cs;
WHILE @@FETCH_STATUS=0
BEGIN
    PRINT @cs
    EXEC(@cs);
    FETCH NEXT FROM c INTO @cs;
END
CLOSE c;
DEALLOCATE c;
GO
DROP TABLE YourTable;

备注

您必须将 / 作为除数运算符替换为 div

使用replace()+-前加分隔符;拆分字符串,然后 sum():


在 SQL Server 2016+ 中你可以使用 string_split().

select 
    t.SumStrings
  , Summed = sum(convert(int,s.value))
from #theSums t
cross apply string_split(replace(replace(SumStrings,'+','|+'),'-','|-'),'|') s
group by t.SumStrings

returns:

+------------+--------+
| SumStrings | Summed |
+------------+--------+
| 1+2        |      3 |
| 1+2-3      |      0 |
+------------+--------+

dbfiddle.uk 演示:http://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=abd084c8fe3758c29c26e29a1f9dfa36


在 SQL 2016 年之前的服务器中,使用 Jeff Moden 的 CSV Splitter table 值函数:

select 
    t.SumStrings
  , Summed = sum(convert(int,s.Item))
from #theSums t
cross apply delimitedsplit8K(replace(replace(SumStrings,'+','|+'),'-','|-'),'|') s
group by t.SumStrings

rextester 演示:http://rextester.com/GTGT29482

returns:

+------------+--------+
| SumStrings | Summed |
+------------+--------+
| 1+2        |      3 |
| 1+2-3      |      0 |
+------------+--------+

拆分字符串的方法有很多种,这个基本前提适用于任何一种方法。

拆分字符串参考:

另一个动态sql

DECLARE @sql VARCHAR(8000) = ''

SELECT @sql = CONCAT( @sql , ' union all select ',  ts.SumStrings)
FROM #theSums ts 

SELECT @sql = STUFF(@sql, 1,10,'')

PRINT @sql 

EXEC (@sql)

使用温度 table。从 sumString 中提取字符串公式并使用 select 执行它,然后将所需的值插入临时 table。逐行执行此操作。

设置 tables: 创建 TABLE sumString( 公式 varchar(20) )

CREATE TABLE temp(
    result varchar(20)
)

INSERT INTO sumString(formula)
VALUES 
('1+3'),
('1+2-3')

解决方法:

DECLARE @expression varchar(20)

WHILE(EXISTS(SELECT 1 FROM sumString))

BEGIN
    SELECT TOP(1) @expression = formula 
    FROM sumString
    INSERT INTO temp
    --the key is to execute with select as a string so the string formula will be evaluate
    exec ('select '+ @exp)  
    DELETE TOP (1) FROM sumString
END

结果:

--check the result--

SELECT * FROM temp

result
4
0