Вы должны просто иметь возможность использовать инструкцию INSERT INTO, чтобы поместить записи прямо в отформатированную таблицу. INSERT INTO будет работать намного лучше, чем при использовании курсора.
INSERT INTO FormattedTable
SELECT
CONVERT(int, EntityId),
CONVERT(int, PerfId),
CONVERT(int, BaseId),
CONVERT(int, UpdateStatus)
FROM RawdataTable
WHERE
IsNumeric(EntityId) = 1
AND IsNumeric(PerfId) = 1
AND IsNumeric(BaseId) = 1
AND IsNumeric(UpdateStatus) = 1
Обратите внимание, что IsNumeric
иногда может возвращать 1 для значений , которые затем завершатся ошибкой при CONVERT . Например, IsNumeric('$e0')
вернет 1, поэтому вам может потребоваться создать более надежную пользовательскую функцию для определения, является ли строка числом, в зависимости от ваших данных.
Кроме того, если вам нужен журнал всех записей, которые не удалось переместить в отформатированную таблицу, просто измените предложение WHERE:
INSERT INTO ErrorLog
SELECT
EntityId,
PerfId,
BaseId,
UpdateStatus
FROM RawdataTable
WHERE
NOT (IsNumeric(EntityId) = 1
AND IsNumeric(PerfId) = 1
AND IsNumeric(BaseId) = 1
AND IsNumeric(UpdateStatus) = 1)
РЕДАКТИРОВАТЬ
Вместо непосредственного использования IsNumeric, может быть лучше создать пользовательский UDF, который сообщит вам, можно ли преобразовать строку в int. Эта функция работала для меня (хотя и с ограниченным тестированием):
CREATE FUNCTION IsInt(@value VARCHAR(50))
RETURNS bit
AS
BEGIN
DECLARE @number AS INT
DECLARE @numeric AS NUMERIC(18,2)
SET @number = 0
IF IsNumeric(@value) = 1
BEGIN
SET @numeric = CONVERT(NUMERIC(18,2), @value)
IF @numeric BETWEEN -2147483648 AND 2147483647
SET @number = CONVERT(INT, @numeric)
END
RETURN @number
END
GO
Обновленный SQL для вставки в отформатированную таблицу будет выглядеть следующим образом:
INSERT INTO FormattedTable
SELECT
CONVERT(int, CONVERT(NUMERIC(18,2), EntityId)),
CONVERT(int, CONVERT(NUMERIC(18,2), PerfId)),
CONVERT(int, CONVERT(NUMERIC(18,2), BaseId)),
CONVERT(int, CONVERT(NUMERIC(18,2), UpdateStatus))
FROM RawdataTable
WHERE
dbo.IsInt(EntityId) = 1
AND dbo.IsInt(PerfId) = 1
AND dbo.IsInt(BaseId) = 1
AND dbo.IsInt(UpdateStatus) = 1
Может быть небольшая странность в обработке NULL (моя функция будет возвращать 0, если передан NULL, даже если INT может быть нулевым), но это можно отрегулировать в зависимости от того, что должно происходить со значениями NULL в RawdataTable
.