Varchar Sql Server Sum

时间:2016-01-05 18:15:59

标签: sql-server vb.net

我有ms访问数据库,我想转换Sql Server。

我的txttotal列有一个($family = "mom dad sister brother"; $f = explode(' ', $family); $nice = ' is nice'; echo $nice_family = implode($nice.', ' ,$f).$nice; )值 我的Sum函数很好地工作了我的旧访问数据库这个查询:

15,50 1,25 10,00

访问检索真值(26,75)

但我尝试使用此查询的SQL Server:

 dtfr = DateTimePicker1.Value 
 dtto = DateTimePicker2.Value



sqlcmd = "SELECT SUM(txttotal) as Total from table WHERE odate >=  CDate('" + dtfr + "') AND  odate <= CDate('" + dtto + "')"

?=我试过float,int,double

SqlException&#34; 将数据类型varchar转换为float时出错&#34;

编辑:我的txttotal列是varchar

3 个答案:

答案 0 :(得分:2)

请勿使用字符串连接将数据输入SQL查询!

这会导致Sql Injection攻击。关于你需要什么值的问题是完全清楚的,但是猜测样本是用逗号分隔的4条记录,并且你只想要每条记录中空格之前的部分,而是这样做:

Dim sql As String = _
     "SELECT SUM(CAST(LEFT(txttotal, " & _
          " CASE WHEN charindex(' ', txttotal) = 0 THEN LEN(txttotal) ELSE charindex(' ', txttotal) - 1 END " & _
         " ) As Integer)) as Total" & _
     " FROM table WHERE odate >=  @DateFrom AND  odate <= @DateTo"

Using cn As New SqlConnection("connection string here"), _
      cmd As New SqlCommand(sql, cn)

    cmd.Parameters.Add("@DateFrom", SqlDbType.DateTime).Value = DateTimePicker1.Value 
    cmd.Parameters.Add("@DateTo", SqlDbType.DateTime).Value = DateTimePicker2.Value 

    cn.Open()
    Dim rdr As SqlDataReader = cmd.ExecuteReader()

    'Do something with the reader here

End Using

或DataSet / DataTable解决方案:

Dim result As New DataTable
Dim sql As String = _
     "SELECT SUM(CAST(LEFT(txttotal, " & _
          " CASE WHEN charindex(' ', txttotal) = 0 THEN LEN(txttotal) ELSE charindex(' ', txttotal) - 1 END " & _
         " ) As Integer)) as Total" & _
     " FROM table WHERE odate >=  @DateFrom AND  odate <= @DateTo"

Using cn As New SqlConnection("connection string here"), _
      cmd As New SqlCommand(sql, cn)

    cmd.Parameters.Add("@DateFrom", SqlDbType.DateTime).Value = DateTimePicker1.Value 
    cmd.Parameters.Add("@DateTo", SqlDbType.DateTime).Value = DateTimePicker2.Value 

    cn.Open()
    result.Load(cmd.ExecuteReader())

End Using

根据一些评论,它开始听起来像空格只是一个缺少的小数分隔符。如果是这种情况,SUM()表达式非常简单:

 SUM(CAST(REPLACE(txttotal, ' ', '.') As numeric(5,2)))

您可能需要,而不是.,具体取决于服务器的区域性安装。 Sql Server 2012还有一个新的PARSE()函数,允许您指定文化,如果升级改变了系统本地文化,则可以消除任何歧义的可能性。

答案 1 :(得分:1)

虽然我并不喜欢以这种方式保存数据,但这听起来是你历史上的原因。 对于SQL Server 2005+(2008+?),您可以转换&#34; varchar&#34;列有效的xml并在其上执行SQL表达式。还有其他可能性,但因此您必须使用过程代码(存储过程/用户定义的函数)和/或临时表ore table变量将日期拆分为表格形式。

因为生成的查询不是那么容易理解,所以我将从一个示例开始,其中varchar类型的变量中包含一个txttotal值的内容。

首先,转换&#34; txttotal&#34;到一个有效的xml片段(您必须添加开始和结束标记,还必须将&#34;,&#34;小数分隔符替换为&#34;。&#34;并将结果转换为XML数据类型。

现在可以选择所有&#34;&#34;节点&#34; ... FROM @ xmltotal.nodes(&#39; / v&#39;)...&#34;从该xml变量中,执行XQuery表达式&#34; ... p.value(&#39;。&#39;,&#39; FLOAT&#39;)...&#34;将它们转换/转换为T-SQL数据类型&#34; FLOAT&#34;最后是值得的SUM()。

DECLARE @txttotal VARCHAR(MAX)
DECLARE @xmltotal XML

SELECT @txttotal = ' 15,50 1,25 10,00 '
SELECT @xmltotal = CAST('<v>'+REPLACE(REPLACE(LTRIM(RTRIM(@txttotal)),',','.'),' ','</v><v>')+'</v>' AS XML)
-- -> <v>15.50</v><v>1.25</v><v>10.00</v>

SELECT SUM(p.value('.', 'FLOAT')) FROM @xmltotal.nodes('/v') t(p)

以上所有内容都可用于编写一个符合您要求的声明性SQL语句......

SELECT (SELECT SUM(p.value('.', 'FLOAT')) FROM xmltotal.nodes('/v') t(p))
FROM
    (
        SELECT
            CAST('<v>'+REPLACE(REPLACE(LTRIM(RTRIM(txttotal)),',','.'),' ','</v><v>')+'</v>' AS XML) AS xmltotal
        FROM
            Table
        -- WHERE
        -- add your required condition here!
    ) T

答案 2 :(得分:0)

首先创建一个拆分字符串函数

CREATE FUNCTION dbo.SplitStrings
(
   @List NVARCHAR(MAX),
   @Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING AS
RETURN
  WITH E1(N)        AS ( SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
                         UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
                         UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1),
       E2(N)        AS (SELECT 1 FROM E1 a, E1 b),
       E4(N)        AS (SELECT 1 FROM E2 a, E2 b),
       E42(N)       AS (SELECT 1 FROM E4 a, E2 b),
       cteTally(N)  AS (SELECT 0 UNION ALL SELECT TOP (DATALENGTH(ISNULL(@List,1))) 
                         ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E42),
       cteStart(N1) AS (SELECT t.N+1 FROM cteTally t
                         WHERE (SUBSTRING(@List,t.N,1) = @Delimiter OR t.N = 0))
  SELECT Item = SUBSTRING(@List, s.N1, ISNULL(NULLIF(CHARINDEX(@Delimiter,@List,s.N1),0)-s.N1,8000))
    FROM cteStart s;

现在使用cross apply将值传递给function并在聚合之前将其拆分。试试这样的事情

SELECT Sum(item) AS Total 
FROM   table 
       CROSS apply dbo.Splitstrings(txttotal, ',') sp 
WHERE  odate BETWEEN x AND y 

检查以下链接以创建拆分字符串函数

  1. http://sqlperformance.com/2012/07/t-sql-queries/split-strings
  2. http://www.sqlservercentral.com/articles/Tally+Table/72993/