Sql server ROSS APPLY正在做什么,或者交叉应用操作符通常是如何工作的?如果是前者,JM_7是完全正确的。它从字符串中剥离出空格和分号。如果数据的其余部分有其他非整型字符,则应将其展开以剥离这些字符。如果是晚些时候,这个话题对几百个字符来说太大了。。。以下是伊
Sql server ROSS APPLY正在做什么,或者交叉应用操作符通常是如何工作的?如果是前者,JM_7是完全正确的。它从字符串中剥离出空格和分号。如果数据的其余部分有其他非整型字符,则应将其展开以剥离这些字符。如果是晚些时候,这个话题对几百个字符来说太大了。。。以下是伊,sql-server,tsql,sql-server-2008-r2,sql-server-2016,Sql Server,Tsql,Sql Server 2008 R2,Sql Server 2016,ROSS APPLY正在做什么,或者交叉应用操作符通常是如何工作的?如果是前者,JM_7是完全正确的。它从字符串中剥离出空格和分号。如果数据的其余部分有其他非整型字符,则应将其展开以剥离这些字符。如果是晚些时候,这个话题对几百个字符来说太大了。。。以下是伊兹克·本·甘的几段非常好的视频。这真的很值得花时间去看它们,@AskMe-Mt-answer已经更新为允许默认值,我添加了与大表的批量更新相关的注释和代码。您只考虑了时间格式:[time]如“[0-9][0-9][0-9][0-9][0-9][
ROSS APPLY正在做什么,或者交叉应用操作符通常是如何工作的?如果是前者,JM_7是完全正确的。它从字符串中剥离出空格和分号。如果数据的其余部分有其他非整型字符,则应将其展开以剥离这些字符。如果是晚些时候,这个话题对几百个字符来说太大了。。。以下是伊兹克·本·甘的几段非常好的视频。这真的很值得花时间去看它们,@AskMe-Mt-answer已经更新为允许默认值,我添加了与大表的批量更新相关的注释和代码。您只考虑了时间格式:[time]如“[0-9][0-9][0-9][0-9][0-9][0-9]”。其他时间格式呢?我是否应该单独设置每个时间格式?而且,在执行SET@r=@@ROWCOUNT时,while循环似乎会一次又一次地继续运行;是不是每一行用该条件更新后@@ROWCOUNT都将为0?您对此有何想法?@AskMe当然,您必须对所需的每一种时间格式执行此操作。因此,您将得到3个循环和3个支持索引。至于ROWCOUNT,在没有要更新的行之后,它将是0,循环将结束。
Time
----------
23:44:33
12:17 09
20 00 20
: :
111913
Time
--------
23:44:33
12:17:09
20:00:20
21:12:00
11:19:13
Update [dbo].[table]
set [TIME] = '21:14:00'
WHERE [TIME] = ' : : '
Update [dbo].[table]
set [time] = replace([TIME], ' ','')
WHERE [time] like '[0-9][0-9] [0-9][0-9] [0-9][0-9]'
Update [dbo].[table]
set [time] = STUFF(STUFF([TIME],3,0,':'),6,0,':')
WHERE [time] like '[0-9][0-9][0-9][0-9][0-9][0-9]'
Update [dbo].[table]
set [time] = replace([time], ' ', ':')
WHERE [time] like '[0-9][0-9]:[0-9][0-9] [0-9][0-9]'
DECLARE @r INT;
WHILE @r > 0
BEGIN
Update TOP (50000) [dbo].[table]
set [time] = replace([TIME], ' ','')
WHERE [time] like '[0-9][0-9] [0-9][0-9] [0-9][0-9]';
SET @r = @@ROWCOUNT;
-- when there is no rows left @@ROWCOUNT will be 0
END;
CREATE NONCLUSTERED INDEX IDX_dbo_table_time
ON [dbo].[table] ([time] ASC)
WHERE [time] like '[0-9][0-9] [0-9][0-9] [0-9][0-9]';
SET NOCOUNT ON;
IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL
DROP TABLE #TestData;
CREATE TABLE #TestData (
TimeVal VARCHAR(20)
);
INSERT #TestData (TimeVal) VALUES
('23:44:33'),
('12:17 09'),
('20 00 20'),
(' : : '),
('111913'),
('12:17'),
('12: 09'),
(' :17 09');
-- before values...
SELECT [Before] = td.TimeVal FROM #TestData td;
-- update problem values...
UPDATE td SET
td.TimeVal = CASE LEN(rr.TimeVal)
WHEN 6 THEN STUFF(STUFF(rr.TimeVal, 5, 0, ':'), 3, 0, ':')
ELSE '21:12:00'
END
FROM
#TestData td
CROSS APPLY ( VALUES (REPLACE(REPLACE(td.TimeVal, ' ', ''), ':', '')) ) rr (TimeVal)
WHERE
td.TimeVal NOT LIKE '[0-9][0-9]:[0-9][0-9]:[0-9][0-9]';
-- after values...
SELECT [After] = td.TimeVal FROM #TestData td;
Before
--------------------
23:44:33
12:17 09
20 00 20
: :
111913
12:17
12: 09
:17 09
After
--------------------
23:44:33
12:17:09
20:00:20
21:12:00
11:19:13
21:12:00
21:12:00
21:12:00
-- create a log table to make it easy to know where you arw in the update process.
CREATE TABLE dbo.TimeValUpdate_LOG (
BegID INT,
EndID INT,
RowsUpdated INT,
BegTime DATETIME,
EndTime DATETIME,
SecsToComplete AS DATEDIFF(SECOND, BegTime, EndTime)
);
-- update script...
DECLARE
@BegID INT = 0,
@EndID INT = 500000,
@BegTime DATETIME,
@EndTime DATETIME;
WHILE EXISTS (SELECT 1 FROM dbo.RealTable rt WHERE rt.PrimaryKey > @BegID)
BEGIN
BEGIN TRY
BEGIN TRANSACTION;
--===================================
SET @BegTime = CURRENT_TIMESTAMP;
INSERT dbo.TimeValUpdate_LOG (BegID, EndID, BegTime) VALUES (@BegID, @EndID, @BegTime);
--=============================================================================
-- update problem values...
UPDATE rt SET
rt.TimeVal = CASE LEN(rr.TimeVal)
WHEN 6 THEN STUFF(STUFF(rr.TimeVal, 5, 0, ':'), 3, 0, ':')
ELSE '21:12:00'
END
FROM
dbo.RealTable rt
CROSS APPLY ( VALUES (REPLACE(REPLACE(rt.TimeVal, ' ', ''), ':', '')) ) rr (TimeVal)
WHERE
rt.PrimaryKey >= @BegID
AND rt.PrimaryKey < @EndID
AND rt.TimeVal NOT LIKE '[0-9][0-9]:[0-9][0-9]:[0-9][0-9]';
--=============================================================================
UPDATE tul SET
tul.RowsUpdated = @@ROWCOUNT,
tul.EndTime = CURRENT_TIMESTAMP
FROM
dbo.TimeValUpdate_LOG tul
WHERE
tul.BegID = @BegID
AND tul.EndID = @EndID;
--===================================
SET @BegID = @EndID + 1;
SET @EndID = @BegID + 500000;
--===================================
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
DECLARE @ErrorNumber INT = ERROR_NUMBER();
DECLARE @ErrorLine INT = ERROR_LINE();
DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE();
DECLARE @ErrorSeverity INT = ERROR_SEVERITY();
DECLARE @ErrorState INT = ERROR_STATE();
PRINT 'Actual error number: ' + CAST(@ErrorNumber AS VARCHAR(10));
PRINT 'Actual line number: ' + CAST(@ErrorLine AS VARCHAR(10));
RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH;
END;
create trigger trCorrectTime on [table] after insert
as
update [table] set [time] = '21:14:00'
from [table]
join inserted on inserted.id=[table].id
where inserted.[TIME] = ' : : '
update [table] set [time] = STUFF(STUFF([table].[time],3,0,':'),6,0,':')
from [table]
join inserted on inserted.id=[table].id
where inserted.[time] like '[0-9][0-9][0-9][0-9][0-9][0-9]'
update [table] set [time] = replace([table].[time], ' ',':')
from [table]
join inserted on inserted.id=[table].id
where inserted.[time] like '[0-9][0-9]_[0-9][0-9]_[0-9][0-9]'
go