【发布时间】:2016-01-14 20:43:23
【问题描述】:
我需要做的是更改 SQL 中的 ActivePath 条目,该条目的值和长度都更改为不同值和长度的不同路径,然后一遍又一遍地运行它,直到没有更多与要更改的 ActivePath 匹配的条目.
这是我目前所拥有的,它适用于我已经知道当前文件路径、新文件路径和文件名的单个文件:
UPDATE [AuroraFileServer].[dbo].[File]
SET ActivePath = REPLACE(ActivePath, 'C:\ProgramData\MyData\FileServer\Data', 'C:\Videos\Archive 1')
WHERE ActivePath IN (SELECT ActivePath FROM [AuroraCore].[dbo].[DeviceEventFile] AS DEF
JOIN [AuroraCore].[dbo].[DeviceEvent] AS DE
ON DE.Id = DEF.DeviceEventId
JOIN [AuroraFileServer].[dbo].[File] AS F
ON DEF.FilePath = F.ActivePath
WHERE DE.Name LIKE 'ACBD13420160111185621001%')
所以概念证明有效,但我需要它更加动态,因为对数百或可能数千个视频运行它是不切实际的。
旧的 ActivePath 位置会根据视频上传到系统的日期在 yyyy/mm/dd 基础上发生变化,其中月份和日期可以是一位或两位数字值,具体取决于月份或日期(1/1 与12/12、1 月 1 日和 12 月 12 日)。新的 ActivePath 需要位于不同的位置,但旧的 ActivePath yyyy/mm/dd + 1 天作为文件存档从主要位置到存档仅 24 小时后。
所以流程需要这样取:
C:\ProgramData\MyData\FileServer\Data\2016\1\13\ACBD13420160111185621001i100.avi
并将其更改为:
C:\Videos\Archive 1\2016\1\14\ACBD13420160111185621001i100.avi
对于数据库中的数百或数千个条目,当然,在文件实际名称更改之前几乎所有内容都发生了变化。
有没有办法让它与创建一个表或索引一起工作,其中所有 ActivePath 条目都可以转储到与 C:\ProgramData... 路径匹配的位置,并使用 a 对该文件运行查询replace 语句使用索引中的单行作为要替换的部分,替换它,然后一遍又一遍地重复遍历列表,直到所有条目都被替换?我已经看到其他遵循这个想法的替换语句,但是所有新旧变量都是已知的,这不是我的情况。
我认为我可以跑:
SELECT ActivePath
FROM AuroraFileServer.dbo.[File]
WHERE ActivePath LIKE 'C:\ProgramData\MyData\FileServer%'
然后将结果返回到包含所有内容的表或索引中,在我的情况下(这将在我的测试环境之外更改),在第 8 个 '\' 被截断并删除重复项以获取列表中的每一行将是 REPLACE 语句的第一个 ' ' 中的单独条目。 REPLACE 语句的第二部分需要复制原始路径的日期部分 + 1 天(因此 31 +1 需要更改月份 +1 以保持日期的工作方式)。这获得了我们运行 REPLACE 语句所需的信息,该语句将循环回到开头并重复,直到该表或索引中的所有行都已完成然后停止。我只是不知道如何做到这一点或从哪里开始。
编辑:
因此,通过使用 bdn02 中的功能,我已经更接近我需要的功能了。这是我目前所拥有的:
(
@olddir varchar(300)
)
RETURNS varchar(300) AS
BEGIN
declare @tmpvar varchar(200)
declare @index int
declare @year varchar(4)
declare @month varchar(2)
declare @day varchar(2)
declare @filename varchar(200)
declare @videodate datetime
declare @newpath varchar(300)
set @tmpvar = replace(@olddir, 'C:\ProgramData\MyData\FileServer\Data\', '')
set @index = charindex('\', @tmpvar)
set @year = substring(@tmpvar, 1, @index-1)
set @tmpvar = substring(@tmpvar, @index+1, len(@tmpvar)-@index)
set @index = charindex('\', @tmpvar)
set @month = substring(@tmpvar, 1, @index-1)
set @tmpvar = substring(@tmpvar, @index+1, len(@tmpvar)-@index)
set @index = charindex('\', @tmpvar)
set @day = substring(@tmpvar, 1, @index-1)
set @filename = substring(@tmpvar, @index+1, len(@tmpvar)-@index)
set @videodate = CONVERT (datetime, @day + '.' + @month + '.' + @year, 104)
set @videodate = DATEADD (day , 1 , @videodate)
--build new path
set @newpath = 'C:\Videos\Archive 1\' + cast(year(@videodate) as varchar) + '\' + cast(month(@videodate) as varchar) + '\' + cast(day(@videodate) as varchar) + '\'
return @newpath
END
使用时返回新路径:
SELECT DISTINCT dbo.ConvertDir(ActivePath)
FROM AuroraFileServer.dbo.[File]
WHERE ActivePath LIKE 'C:\ProgramData\MyData\FileServer%'
好的,现在:
(
@olddir varchar(300)
)
RETURNS varchar(300) AS
BEGIN
declare @tmpvar varchar(200)
declare @index int
declare @year varchar(4)
declare @month varchar(2)
declare @day varchar(2)
declare @filename varchar(200)
declare @videodate datetime
declare @oldpath varchar(300)
set @tmpvar = replace(@olddir, 'C:\ProgramData\MyData\FileServer\Data\', '')
set @index = charindex('\', @tmpvar)
set @year = substring(@tmpvar, 1, @index-1)
set @tmpvar = substring(@tmpvar, @index+1, len(@tmpvar)-@index)
set @index = charindex('\', @tmpvar)
set @month = substring(@tmpvar, 1, @index-1)
set @tmpvar = substring(@tmpvar, @index+1, len(@tmpvar)-@index)
set @index = charindex('\', @tmpvar)
set @day = substring(@tmpvar, 1, @index-1)
set @filename = substring(@tmpvar, @index+1, len(@tmpvar)-@index)
set @videodate = CONVERT (datetime, @day + '.' + @month + '.' + @year, 104)
--build new path
set @oldpath = 'C:\ProgramData\MyData\FileServer\Data\' + cast(year(@videodate) as varchar) + '\' + cast(month(@videodate) as varchar) + '\' + cast(day(@videodate) as varchar) + '\'
return @oldpath
END
使用时返回旧路径:
SELECT DISTINCT dbo.ConvertDir1(ActivePath)
FROM AuroraFileServer.dbo.[File]
WHERE ActivePath LIKE 'C:\ProgramData\MyData\FileServer%'
完美,所以现在我有了没有重复的旧路径和新路径。
现在我正在尝试利用一个新函数将两个 udf 放在一个带有 WHERE 循环的替换语句中。问题是我得到“找不到列“dbo”或用户定义的函数或聚合“dbo.ConvertDir”,或者名称不明确。在我的 dbo.ConvertDir 和 dbo.ConvertDir1 的新函数中。我的默认架构是 dbo。这是函数:
DECLARE @oldpath TABLE (old varchar(255))
DECLARE @newpath TABLE (new varchar(255))
INSERT INTO @oldpath (OLD)
SELECT DISTINCT dbo.ConvertDir1(oldpath);
INSERT INTO @newpath (NEW)
SELECT DISTINCT dbo.ConvertDir(newpath);
WHILE (1=1)
BEGIN
UPDATE f
SET f.ActivePath = REPLACE(f.ActivePath, o.old, n.new)
FROM AuroraFileServer.dbo.[File] AS f,
@oldpath AS o,
@newpath AS n
WHERE f.ActivePath LIKE 'C:\ProgramData\MyData\FileServer%'
IF @@ROWCOUNT = 0
BREAK
END
SELECT * FROM AuroraFileServer.dbo.[File]
我做错了什么?
【问题讨论】:
-
我觉得写一个特定的函数来获取旧路径作为输入,解析它,添加一天并返回新路径更简单。您可以直接在选择中使用它
-
我可能需要进一步解释,但让我对这种方法进行一些研究,看看我想出了什么。
标签: sql sql-server replace user-defined-functions udf