2016-01-05 155 views
1

我有MS访问数据库,我想转换Sql Server。Varchar Sql Server总和

我txttotal列有(15,50 1,25 10,00)值 我Sum函数伟大的工作我的旧Access数据库的查询:

dtfr = DateTimePicker1.Value 
dtto = DateTimePicker2.Value 



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

访问检索真值(26,75)

但我想的Sql使用此查询服务器:

sqlcmd = "SELECT SUM(CAST(txttotal as ?)) as Total from table WHERE odate BETWEEN '" + dtfr + "' AND '" + dtto + "'" 

=我试过浮动,整型,双

SQLEXCEPTION “误差变换数据类型为varchar浮

编辑:我的txttotal列是VARCHAR

+1

你确定它不是文化的东西吗?你尝试过吗?而不是,为您的小数点分隔符? – itsme86

+0

我需要使用(,)字符作为分隔符。 – Mysta

+0

你使用的是c#还是vb.net? –

回答

2

不要使用字符串连接将数据放入SQL查询!

这会导致Sql注入攻击。现在的问题是什么样的价值观,你所需要的,但猜测该样品是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还有一个新的功能,允许您指定文化,消除任何模糊不清的机会,如果升级改变系统本地文化。

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/
+0

总而言之işlennveritürüvarchar ge ersiz。 Translate:为果汁机处理器varchar处理的数据类型无效。 – Mysta

+0

编辑:我的txttotal列是varchar – Mysta

1

Allthough我不是那种持有数据的粉丝,但这听起来是你有历史原因。 对于SQL Server 2005+(2008+?)您可以将“varchar”列转换为有效的xml并在其上执行SQL表达式。还有其他的可能性,但是因此你必须使用过程代码(存储过程/用户定义的函数)和/或临时表或表变量来将日期分解成表格形式。

因为生成的查询不容易遵循,我将从一个例子开始,在这个例子中,您有一个类型为varchar的变量中的一个txttotal值的内容。

首先,将“txttotal”转换为有效的xml片段(您必须添加开始和结束标签,并且还必须将“,”小数点分隔符替换为“。”,并将结果转换为XML数据

现在可以从该xml变量中选择所有“”节点“...从@ xmltotal.nodes('/ v')...”,执行XQuery表达式“... p”。值(“”,‘浮动’)......”他们转换/它们转换成T-SQL数据类型‘浮动’,最后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语句s ...

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