sql - 将字符串拆分到表中

标签 sql sql-server string sql-server-2008 t-sql

我有一个字符串(代表文件夹路径)。 最大级别数已知(子子文件夹) 最小级别数已知(根目录不包含文件)。 文件夹名称可以包含空格。 没有说明示例中的a是文件夹还是文件............ 我希望将该字符串分成几列。

CREATE TABLE TESTDATA([path] [nvarchar](max))
INSERT INTO TESTDATA (path) VALUES (N'/a/)
INSERT INTO TESTDATA (path) VALUES (N'/a/ab/filename1)
INSERT INTO TESTDATA (path) VALUES (N'/a/ab/abc/filename2)
INSERT INTO TESTDATA (path) VALUES (N'/a/ab/abc/filename3)
INSERT INTO TESTDATA (path) VALUES (N'/a/ab/abc/abcd/filename4)
INSERT INTO TESTDATA (path) VALUES (N'/a/ac/ac e/filename5)

TESTDATA 现在看起来像

|----------path-----------------|
/a
/a/ab/filename1
/a/ab/abc/filename2
/a/ab/abc/filename3
/a/ab/abc/abcd/filename4
/a/ac/ac e/filename5

但我需要它看起来像

filename--|--root--|--folder--|--subfolder--|--subsubfolder--|
----------|--------|----------|-------------|----------------|
filename1-|---a----|----ab----|
filename2-|---a----|----ab----|-----abc-----|
filename3-|---a----|----ab----|-----abc-----|
filename4-|---a----|----ab----|-----abc-----|-------abcd-----|
filename5-|---a----|----ac----|-----ac e----|

我该如何解决这个问题?

我想我应该用 SUBSTRINGCHARINDEX 做一些事情,但我尝试了一千件事;永远不会做对。当字符串包含空格时,SUBSTRING 似乎会停止在字符串中搜索。

最佳答案

使用CHARINDEXSUBSTRING是一个很好的方法。请记住,CHARINDEX 可以采用第三个参数来指定搜索的起点。使用它,您可以找到第二个 / 和第三个 /,依此类推。分解问题的一种方法是使用相互构建的子查询,一次解决问题的一小部分。以下是使用连续的公共(public)表表达式将文件名分解为子子文件夹级别的示例:

with root as (
  select
    path,
    left(path, charindex('/', path, 2) - 1) as root,
    substring(path, charindex('/', path, 2), 1000) as rest
  from testdata
), folder as (
  select
    path,
    root,
    case when charindex('/', rest, 2) > 0
      then left(rest, charindex('/', rest, 2) - 1)
      else '' 
    end as folder,
    case when charindex('/', rest, 2) > 0
      then substring(rest, charindex('/', rest, 2), 1000)
      else rest
    end as rest
  from root
), subfolder as (
  select
    path,
    root,
    folder,
    case when charindex('/', rest, 2) > 0
      then left(rest, charindex('/', rest, 2) - 1)
      else '' 
    end as subfolder,
    case when charindex('/', rest, 2) > 0
      then substring(rest, charindex('/', rest, 2), 1000)
      else rest
    end as rest
  from folder
), subsubfolder as (
  select
    path,
    root,
    folder,
    subfolder,
    case when charindex('/', rest, 2) > 0
      then left(rest, charindex('/', rest, 2) - 1)
      else '' 
    end as subsubfolder,
    case when charindex('/', rest, 2) > 0
      then substring(rest, charindex('/', rest, 2), 1000)
      else rest
    end as rest
  from subfolder
)
select
  path,
  rest as filename,
  root,
  folder,
  subfolder,
  subsubfolder
from subsubfolder;

演示:http://www.sqlfiddle.com/#!3/e91eb/36

示例输出:

PATH                      FILENAME    ROOT  FOLDER  SUBFOLDER  SUBSUBFOLDER
------------------------  ----------  ----  ------  ---------  ------------  
/a/                       /           /a               
/a/ab/filename1           /filename1  /a    /ab          
/a/ab/abc/filename2       /filename2  /a    /ab     /abc     
/a/ab/abc/filename3       /filename3  /a    /ab     /abc     
/a/ab/abc/abcd/filename4  /filename4  /a    /ab     /abc       /abcd
/a/ac/ac e/filename5      /filename5  /a    /ac     /ac e

注意:删除我保留在文件夹名称中的 / 可以使用 SUBSTRING(part, 2, 1000) 轻松完成SUBSTITUTE(part, '/', '')

关于sql - 将字符串拆分到表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13418681/

相关文章:

sql-server - 我可以在 ssrs 报告中添加一个过滤器按钮吗?

javascript - 使用正则表达式操作字符串

html - MySQL 数据库错误 #1064

php - 过时的 SQL 注入(inject)预防器?

sql - Informix 的 Row_number() 函数

python - 如何在 python 中将 urlopen 转换为字符串

string - 如何从 std::borrow::Cow<str> 获取 &str 或 String?

php - PHP MYSQL 组合的转换问题

sql-server - 我应该如何为现有数据库表定义复合主键?

sql-server - 将外键添加到复合键时出错