SQL Server 游标
我想将数据从一个表(原始数据,所有列都是 VARCHAR)复制到另一个表(使用相应的列格式进行格式化)。
为了将数据从 rawdata
表复制到 formatted
表中,我使用游标来识别受影响的行。我需要在错误日志表中记录该特定行,跳过它,然后继续复制剩余的行。
复制需要更多时间。还有其他方法可以实现这一目标吗? 这是我的查询
DECLARE @EntityId Varchar(16) ,
@PerfId Varchar(16),
@BaseId Varchar(16) ,
@UpdateStatus Varchar(16)
DECLARE CursorSample CURSOR FOR
SELECT EntityId, PerfId, BaseId, @UpdateStatus
FROM RawdataTable
--Returns 204,000 rows
OPEN CursorSample
FETCH NEXT FROM CursorSample INTO @EntityId,@PerfId,@BaseId,@UpdateStatus
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
--try insertting row in formatted table
Insert into FormattedTable
(EntityId,PerfId,BaseId,UpdateStatus)
Values
(Convert(int,@EntityId),
Convert(int,@PerfId),
Convert(int,@BaseId),
Convert(int,@UpdateStatus))
END TRY
BEGIN CATCH
--capture Error EntityId in errorlog table
Insert into ERROR_LOG
(TableError_Message,Error_Procedure,Error_Log_Time)
Values
(Error_Message()+@EntityId,’xxx’, GETDATE())
END CATCH
FETCH NEXT FROM outerCursor INTO @EntityId, @BaseId
END
CLOSE CursorSample
DEALLOCATE CursorSampler –cleanup CursorSample
I want to copy data from one table (rawdata, all columns are VARCHAR) to another table (formatted with corresponding column format).
For copying data from the rawdata
table into formatted
table, I'm using cursor in order to identify which row is affected. I need to log that particular row in an error log table, skip it, and continue copying remaining rows.
It takes more time to copying. Is there any other way to achieve this?
this is my query
DECLARE @EntityId Varchar(16) ,
@PerfId Varchar(16),
@BaseId Varchar(16) ,
@UpdateStatus Varchar(16)
DECLARE CursorSample CURSOR FOR
SELECT EntityId, PerfId, BaseId, @UpdateStatus
FROM RawdataTable
--Returns 204,000 rows
OPEN CursorSample
FETCH NEXT FROM CursorSample INTO @EntityId,@PerfId,@BaseId,@UpdateStatus
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
--try insertting row in formatted table
Insert into FormattedTable
(EntityId,PerfId,BaseId,UpdateStatus)
Values
(Convert(int,@EntityId),
Convert(int,@PerfId),
Convert(int,@BaseId),
Convert(int,@UpdateStatus))
END TRY
BEGIN CATCH
--capture Error EntityId in errorlog table
Insert into ERROR_LOG
(TableError_Message,Error_Procedure,Error_Log_Time)
Values
(Error_Message()+@EntityId,’xxx’, GETDATE())
END CATCH
FETCH NEXT FROM outerCursor INTO @EntityId, @BaseId
END
CLOSE CursorSample
DEALLOCATE CursorSampler –cleanup CursorSample
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您应该能够使用 INSERT INTO 语句将记录直接放入格式化表中。 INSERT INTO 的性能比使用游标好得多。
请注意,
IsNumeric
有时可能会为 将在 CONVERT 时失败。例如,IsNumeric('$e0')
将返回 1,因此您可能需要创建一个更强大的用户定义函数来确定字符串是否为数字,具体取决于您的数据。另外,如果您需要无法移动到格式化表中的所有记录的日志,只需修改 WHERE 子句:
EDIT
与其直接使用 IsNumeric,不如创建一个自定义 UDF 来告诉您字符串是否可以转换为 int。这个函数对我有用(尽管测试有限):
用于插入格式化表的更新的 SQL 看起来像这样:
处理 NULL 可能有点奇怪(如果传入 NULL,我的函数将返回 0,即使尽管 INT 当然可以为 null),但是可以根据
RawdataTable
中的 NULL 值应该发生的情况进行调整。You should just be able to use a INSERT INTO statement to put the records directly into the formatted table. INSERT INTO will perform much better than using a cursor.
Note that
IsNumeric
can sometimes return 1 for values that will then fail on CONVERT. For example,IsNumeric('$e0')
will return 1, so you may need to create a more robust user defined function for determining if a string is a number, depending on your data.Also, if you need a log of all records that could not be moved into the formatted table, just modify the WHERE clause:
EDIT
Rather than using IsNumeric directly, it may be better to create a custom UDF that will tell you if a string can be converted to an int. This function worked for me (albeit with limited testing):
The updated SQL for the insert into the formatted table would then look like this:
There may be a little weirdness around handling NULLs (my function will return 0 if NULL is passed in, even though an INT can certainly be null), but that can be adjusted depending on what is supposed to happen with NULL values in the
RawdataTable
.您可以在游标定义中放置一个
WHERE
子句,以便首先只选择有效记录。您可能需要创建一个函数来确定有效性,但它应该比循环它们更快。实际上,您可能想要创建一个包含无效记录的临时表,以便可以记录错误,然后仅在临时表中没有的行上定义游标。
You can put a
WHERE
clause in your cursor definition so that only valid records are selected in the first place. You might need to create a function to determine validity, but it should be faster than looping over them.Actually, you might want to create a temp table of the invalid records, so that you can log the errors, then define the cursor only on the rows that are not in the temp table.
插入比光标工作得更好。
由于光标仅在您的 PC 内存中工作,并且会减慢 SQL Server 的优化速度。我们应该避免使用游标,但(当然)有些情况下无法避免使用游标。
Insert into will work much more better than Cursor.
As Cursor work solely in Memory of your PC and slows down the optimization of SQL Server. We should avoid using Cursors but (of course) there are situations where usage of Cursor cannot be avoided.