执行以下代码会触发错误:
System.Data.SqlClient.SqlException:'无法将 char 值转换为货币。 char 值的语法不正确。
一切都很好,直到我添加了用于排序目的的第二个参数。 为了清晰起见,代码进行了简化。
query as String = "
SELECT a, b, c
FROM DataTable
WHERE c = @PARAM
ORDER BY
CASE @SORTCOLUMN
WHEN 1 THEN a
WHEN 2 THEN b
WHEN 3 THEN c
END"
Dim param As String = "myprarameter"
Dim sortcolumn as Integer = 1
result = connection.Query(Of MyType)(query, New With {Key .PARAM = param, Key .SORTCOLUMN = sortcolumn})
更新:
经过数小时的测试,我已将其范围缩小到纯粹的 SQL 问题,而不是 Dapper 或 .NET Framework。
以下是我的发现: 一切正常,直到
CASE WHEN
中使用的所有列都具有相同类型(或可以轻松相互转换的类型甚至值)。一旦列类型不同,值无法转换,则返回类型转换错误。似乎它正在尝试将 CASE WHEN
选择的列的类型转换为第一个 WHEN
列的类型。
举两个例子。为了简单起见,我删除了变量。
这有效:
CREATE TABLE #TestTable1
(col1 money, col2 money)
INSERT INTO #TestTable1
(col1, col2)
VALUES
(1, 30),
(2, 20),
(3, 10)
SELECT col1, col2
FROM #TestTable1
ORDER BY
CASE 2
WHEN 1 THEN col1
WHEN 2 THEN col2
END
DROP TABLE #TestTable1
但这不起作用。退货:
无法将字符值转换为货币。 char 值的语法不正确。
CREATE TABLE #TestTable2
(col1 money, col2 varchar(20))
INSERT INTO #TestTable2
(col1, col2)
VALUES
(1, 'cc'),
(2, 'bb'),
(3, 'aa')
SELECT col1, col2
FROM #TestTable2
ORDER BY
CASE 2
WHEN 1 THEN col1
WHEN 2 THEN col2
END
DROP TABLE #TestTable2
我使用兼容性级别为 150 的 Azure SQL。 我相应地更新了标题和标签。
更新2: 我正在尝试以第二个参数的形式向 @forpas 解决方案添加一个复杂性,该参数将告诉顺序。我在
CASE
中使用了 CASE
,但这会返回一些语法错误。
仅 ORDER
部分。其余的没变。
ORDER BY
CASE @SORTORDER
WHEN 'a' THEN
(CASE @SORTCOLUMN
WHEN 1 THEN col1
WHEN 2 THEN col2
END,
CASE @SORTCOLUMN
WHEN 3 THEN col3
WHEN 4 THEN col4
END) ASC
WHEN 'd' THEN
(CASE @SORTCOLUMN
WHEN 1 THEN col1
WHEN 2 THEN col2
END,
CASE @SORTCOLUMN
WHEN 3 THEN col3
WHEN 4 THEN col4
END) DESC
END
只需将 SQL 创建为 nvarchar 并按如下方式执行:
DECLARE @SQL NVARCHAR(MAX) = N'
SELECT a, b, c
FROM DataTable
WHERE c = @PARAM
ORDER BY ' + (CASE @SORTCOLUMN WHEN 1 THEN 'a' WHEN 2 THEN 'b' WHEN 3 THEN 'c' ELSE 'a' END);
EXEC sp_Executesql @SQL,
N'@Param int',
@Param = @Param;
VB 中
query as String = "DECLARE @SQL NVARCHAR(MAX) = N'SELECT a, b, c FROM DataTable
WHERE c = @PARAM
ORDER BY ' + (CASE @SORTCOLUMN WHEN 1 THEN 'a' WHEN 2 THEN 'b' WHEN 3 THEN 'c' ELSE 'a' END);
EXEC sp_Executesql @SQL,
N'@Param int',
@Param = @Param;"
一种解决方案是将
CASE
语句拆分为所需的多个 CASE
语句,以便每个语句都包含具有相同或相似可转换数据类型的列:
CREATE TABLE #TestTable2
(col1 money, col2 decimal(18, 2), col3 varchar(20))
INSERT INTO #TestTable2
(col1, col2, col3)
VALUES
(1, 5.5, 'cc'),
(2, 1.8, 'bb'),
(3, 3.3, 'aa');
DECLARE @SORTCOLUMN INT = 1; -- 1 or 2 or 3
SELECT col1, col2, col3
FROM #TestTable2
ORDER BY
CASE @SORTCOLUMN
WHEN 1 THEN col1
WHEN 2 THEN col2
END,
CASE @SORTCOLUMN
WHEN 3 THEN col3
END
DROP TABLE #TestTable2
查看演示。
试试这个。
query as String = "
SELECT a, b, c
FROM DataTable
WHERE c = @PARAM
ORDER BY
CASE @SORTCOLUMN
WHEN '1' THEN a
WHEN '2' THEN b
WHEN '3' THEN c
END"