sql server - 检查是否可以强制转换然后在order子句中使用

时间:2016-08-31 09:25:28

标签: sql-server tsql sql-server-2005

我有一个varchar(20)列,需要转换为int并在order子句中使用。但是当可以转换时,事情是可以的。我的代码:

            SELECT    DISTINCT people.ParYear,CAST(people.ParID As int), people.Pfamily, people.Pname
            FROM               people 
            WHERE            people.osID    = @osID 
                         AND people.shID    = @shID
                         AND people.ParYear = @ParYear
               ORDER BY        people.ParYear, CAST(people.ParID As int)

那么我怎样才能避免错误转发失败等消息!

示例数据:

|的 OSID |的 SHID |的 ParYear |的 ParID |的 Pfamily | PNAME |
| ------ | ------- | ----------- | -------- | --------- | --- -------- |
| 4 | 12 | 2016 | 5 | A | A1 |
| 4 | 12 | 2016 | 8-1 | AB | A2 |
| 4 | 12 | 2016 | 7 | AC | A3 |
| 4 | 12 | 2016 | 4 | ACD | A4 |
| 4 | 12 | 2016 | 1 | AD | A5 |
| 4 | 12 | 2016 | 6 | AF | A6 |
| 4 | 12 | 2016 | 3 | AFF | A7 |
| 4 | 12 | 2016 | 2 | AG | A8 |
| 4 | 12 | 2016 | 12 * 3 | AN | A9 |
| 4 | 12 | 2016 | 9-4 | AI | A0 |
| 4 | 12 | 2016 | 178/2 | AS | A00 |
| ----- | -------- | ----------- | -------- | --------- | --- -------- |

需要订购:
1
2
3
4
5
6
7
8-1
9- 4
12个* 3个
178/2

2 个答案:

答案 0 :(得分:2)

我看到为旧版SQL Server执行此操作的唯一方法(2005年有问题,新版本有更好/其他工具),将使用类似PATINDEX的内容检查进入值:

考虑:

DECLARE @asVarchar VARCHAR(200);
DECLARE @asVarchar2 VARCHAR(200);
SET @asVarchar = '1*2';
SET @asVarchar2 = '12';
DECLARE @asInt INT

IF (PATINDEX('%[^0-9]%', @asVarchar) = 0) BEGIN
    SET @asInt = CAST(@asVarchar AS INT)
END
SELECT @asInt, @asVarchar     -- returns: null, '1*2'

IF (PATINDEX('%[^0-9]%', @asVarchar2) = 0) BEGIN
    SET @asInt = CAST(@asVarchar2 AS INT)
END
SELECT @asInt, @asVarchar     -- returns: 12, '12'

使用PATINDEX我们测试字符串@asVarchar@asVarchar2的内容是否包含0-9以外的内容,如果不包含 - 我们将其转换为int进入@asInt

因此,在我的示例'1*2'中包含*并且无法转换,因此@asIntNULL
'12'仅包含0-9,因此我们可以转换它,@asInt变为12

然而,它不会是"漂亮"并且性能可能是复杂数据中的一个问题,因此重新考虑整个方法以及底层问题是否可以通过不同方法进行不同解决可能是值得的。

编辑:
鉴于您对样本数据的更新,我认为沿着这种思路可能会出现以下情况:

DECLARE @t AS TABLE (sortCol varchar(200))
INSERT INTO @t VALUES ('178/2')
INSERT INTO @t VALUES ('12*3')
INSERT INTO @t VALUES ('9- 4')
INSERT INTO @t VALUES ('8-1')
INSERT INTO @t VALUES ('1')
INSERT INTO @t VALUES ('2')
INSERT INTO @t VALUES ('3')
INSERT INTO @t VALUES ('4')
INSERT INTO @t VALUES ('5')
INSERT INTO @t VALUES ('6')
INSERT INTO @t VALUES ('7')

SELECT *
FROM @t
ORDER BY 
 CAST(SUBSTRING(sortCol, 1, 
               CASE WHEN PATINDEX('%[^0-9]%', sortCol) = 0 THEN LEN(sortCol) 
               ELSE  PATINDEX('%[^0-9]%', sortCol) - 1 END
     ) AS INT)

答案 1 :(得分:-2)

使用convert进行类型转换。

SELECT DISTINCT people.ParYear,CAST(people.ParID As int), people.Pfamily,
people.Pname FROM people
WHERE people.osID = @osID
AND people.shID = @shID
AND people.ParYear = @ParYear
ORDER BY people.ParYear, CONVERT(INT,people.ParID)

希望它会有所帮助。