一般的时候数据库设计中,有一对多或多对多的关系往往会设计一个表来存储这种关系的对应,但有时数据库结构我们是不能修改的,只能允许我们读取,现在假如有一下的数据表,需要我们来拆分字段char_array了。

有一段有趣的SQL 代码可以很好的解决这个问题:
1
IF OBJECT_ID('dbo.Nums') IS NOT NULL2
DROP TABLE dbo.Nums;3
GO4
CREATE TABLE dbo.Nums(n INT NOT NULL PRIMARY KEY);5
DECLARE @max AS INT, @rc AS INT;6
SET @max = 1000000;7
SET @rc = 1;8

9
INSERT INTO Nums VALUES(1);10
WHILE @rc * 2 <= @max11
BEGIN12
INSERT INTO dbo.Nums SELECT n + @rc FROM dbo.Nums;13
SET @rc = @rc * 2;14
END15

16
INSERT INTO dbo.Nums 17
SELECT n + @rc FROM dbo.Nums WHERE n + @rc <= @max;18
GO1
IF OBJECT_ID('dbo.Arrays') IS NOT NULL2
DROP TABLE dbo.Arrays;3
GO4
-- http://weiweictgu.cnblogs.com5
--come from sql server 2005 t-sql querying6
CREATE TABLE dbo.Arrays7
(8
arrid VARCHAR(10) NOT NULL PRIMARY KEY,9
array VARCHAR(8000) NOT NULL10
)11

12
INSERT INTO Arrays(arrid, array) VALUES('A', '20,22,25,25,14');13
INSERT INTO Arrays(arrid, array) VALUES('B', '30,33,28');14
INSERT INTO Arrays(arrid, array) VALUES('C', '12,10,8,12,12,13,12,14,10,9');15
INSERT INTO Arrays(arrid, array) VALUES('D', '-4,-6,-4,-2');16
GO1
-- Solution to Separating Elements Problem, Step 12
SELECT arrid, array, n3
FROM dbo.Arrays4
JOIN dbo.Nums5
ON n <= LEN(array)6
AND SUBSTRING(array, n, 1) = ',';7

8
-- Solution to Separating Elements Problem, Step 29
SELECT arrid, array, n10
FROM dbo.Arrays11
JOIN dbo.Nums12
ON n <= LEN(array)13
AND SUBSTRING(',' + array, n, 1) = ',';14

15
-- Solution to Separating Elements Problem, Step 316
SELECT arrid, 17
SUBSTRING(array, n, CHARINDEX(',', array + ',', n) - n) AS element18
FROM dbo.Arrays19
JOIN dbo.Nums20
ON n <= LEN(array)21
AND SUBSTRING(',' + array, n, 1) = ',';22

23
-- Solution to Separating Elements Problem, Step 424
SELECT arrid,25
n - LEN(REPLACE(LEFT(array, n), ',', '')) + 1 AS pos,26
CAST(SUBSTRING(array, n, CHARINDEX(',', array + ',', n) - n)27
AS INT) AS element28
FROM dbo.Arrays29
JOIN dbo.Nums30
ON n <= LEN(array)31
AND SUBSTRING(',' + array, n, 1) = ',';在SQL Server2005中没有必要再建立数字辅助表,可以使用递归CTE来拆分字段,但这种方法受限于
SQL Server2005的递归语法,在其他数据库中需要考虑其他的方式来实现。
1
-- Solution based on Recursive CTEs2
WITH SplitCTE AS3
(4
SELECT arrid, 1 AS pos, 1 AS startpos,5
CHARINDEX(',', array + ',') - 1 AS endpos6
FROM dbo.Arrays7
WHERE LEN(array) > 08

9
UNION ALL10

11
SELECT Prv.arrid, Prv.pos + 1, Prv.endpos + 2,12
CHARINDEX(',', Cur.array + ',', Prv.endpos + 2) - 113
FROM SplitCTE AS Prv14
JOIN dbo.Arrays AS Cur15
ON Cur.arrid = Prv.arrid16
AND CHARINDEX(',', Cur.array + ',', Prv.endpos + 2) > 017
)18
SELECT A.arrid, pos,19
CAST(SUBSTRING(array, startpos, endpos-startpos+1) AS INT) AS element20
FROM dbo.Arrays AS A21
JOIN SplitCTE AS S22
ON S.arrid = A.arrid23
ORDER BY arrid, pos;通过上面的演示代码你应该已经明白怎么将一个字段的字符如何拆分开来了。
注:此代码摘选自《SQL Server 2005 技术内幕T—SQL查询》一书的源码,此文是该书里面的一个小的应用实例。