我试图编写一个执行批量插入的程序,在这个批量插入中,我将所有未解析为正确数据类型的数据转换为null。我仍然需要在那里插入其余的行。
这不是一个问题,但我还需要记录这些错误发生的位置。但是我在执行此操作时遇到了一些麻烦,因为您无法在函数中插入。
这是我尝试过的功能:
CREATE FUNCTION [dbo].[ReplaceNonNumericInt]
(@strText NVARCHAR(100),
@strField nvarchar(100),
@LoanOrShare nvarchar(1))
RETURNS INT
AS
BEGIN
DECLARE @Return as int
IF TRY_CAST(@strText AS INT) > 0
BEGIN
SET @Return = CAST(@strText as int)
END
ELSE BEGIN
IF @LoanOrShare = 'L'
BEGIN
INSERT INTO tblLoan_ImportErrors(Error, Field, Row)
VALUES('Type Conversion Failure', @strField, @@IDENTITY + 1)
SET @Return = NULL
END
SET @Return = NULL
END
RETURN @Return
END
但是这不起作用,因为你不能在函数中插入语句。我发现的解决方案是"使用存储过程"但是我不知道如何让存储过程像函数一样返回。我不能使用输出参数,因为这是从插入语句中调用的。
以下是我用来插入记录的代码:
CREATE PROCEDURE [dbo].[sp_insLoans]
@FileLocation nvarchar(500)
AS
CREATE TABLE #tmpLOAN (
[RecordCode] NVARCHAR (100) NULL,
[AccountNum] NVARCHAR (100) NULL,
[MembersName] NVARCHAR (100) NULL,
[MailingAddress] NVARCHAR (100) NULL,
[City] NVARCHAR (100) NULL,
[State] NVARCHAR (100) NULL,
[ZipCode] NVARCHAR (100) NULL,
[OtherStreet] NVARCHAR (100) NULL,
[LoanTypeCode] NVARCHAR (100) NULL,
[PaymentAmt] NVARCHAR(100) NULL,
[PurposeCode] NVARCHAR (100) NULL,
[LoanTerm] NVARCHAR (100) NULL,
[PaymentFreqCode] NVARCHAR (100) NULL,
[DateOfLoan] NVARCHAR(100) NULL,
[OriginalLoanAmt] NVARCHAR(100) NULL,
[InterestRate] NVARCHAR(100) NULL,
[InterestRateCode] NVARCHAR (100) NULL,
[CurrentLoanBal] NVARCHAR(100) NULL,
[DateOfLastActivity] NVARCHAR(100) NULL,
[LastActivityCode] NVARCHAR (100) NULL,
[NextPaymentDueDate] NVARCHAR(100) NULL,
[AccruedInt] NVARCHAR(100) NULL,
[CreditLimit] NVARCHAR(100) NULL,
[SSN] NVARCHAR (100) NULL,
[DaysDelinq] nvarchar(100) NULL,
[Delinq30_59] nvarchar(100) NULL,
[Delinq60_89] nvarchar(100) NULL,
[Delinq90_119] nvarchar(100) NULL,
[Delinq120_plus] nvarchar(100) NULL,
[InsiderCode] NVARCHAR (100) NULL,
[LoanOfficer_CCInit] NVARCHAR (100) NULL,
[CreditScore] nvarchar(100) NULL,
[ChargeOffAmt] NVARCHAR(100) NULL,
[LoanRiskGrade] NVARCHAR (100) NULL,
[RemainingPayments] nvarchar(100) NULL,
[LoanCollateralCode] NVARCHAR (100) NULL,
[LastFileMaintDate] NVARCHAR(100) NULL,
[LastFIleMaintUser] NVARCHAR (100) NULL,
[BranchId] NVARCHAR (100) NULL
)
DECLARE @sql NVARCHAR(4000) = 'BULK INSERT #tmpLOAN FROM ''' + @FileLocation + ''' WITH ( FIELDTERMINATOR ='''+ CHAR(9) +''', ROWTERMINATOR ='''+CHAR(10)+''' )';
exec(@sql)
INSERT INTO tblLOAN(RecordCode,AccountNum,MembersName,MailingAddress,City,[State],ZipCode,OtherStreet,LoanTypeCode,PaymentAmt,PurposeCode,LoanTerm,PaymentFreqCode,DateOfLoan,OriginalLoanAmt,InterestRate,InterestRateCode,CurrentLoanBal,DateOfLastActivity,LastActivityCode,NextPaymentDueDate,AccruedInt,CreditLimit,SSN,DaysDelinq,dbo.Delinq30_59,Delinq60_89,Delinq90_119,Delinq120_plus,InsiderCode,LoanOfficer_CCInit,CreditScore,ChargeOffAmt,LoanRiskGrade,RemainingPayments,LoanCollateralCode,LastFileMaintDate,LastFileMaintUser,BranchId)
SELECT LTRIM(RTRIM(RecordCode)),
LTRIM(RTRIM(AccountNum)),
LTRIM(RTRIM(MembersName)),
LTRIM(RTRIM(MailingAddress)),
LTRIM(RTRIM(City)),
LTRIM(RTRIM([State])),
LTRIM(RTRIM(ZipCode)),
LTRIM(RTRIM(OtherStreet)),
LTRIM(RTRIM(LoanTypeCode)),
dbo.ReplaceNonNumericDecimal((RTRIM(PaymentAmt))),
LTRIM(RTRIM(PurposeCode)),
LTRIM(RTRIM(LoanTerm)),
LTRIM(RTRIM(PaymentFreqCode)),
dbo.DateOrNull((LTRIM(RTRIM(DateOfLoan)))),
dbo.ReplaceNonNumericDecimal(LTRIM(RTRIM(OriginalLoanAmt))),
dbo.ReplaceNonNumericDecimal(LTRIM(RTRIM(InterestRate))),
LTRIM(RTRIM(InterestRateCode)),
dbo.ReplaceNonNumericDecimal(LTRIM(RTRIM(CurrentLoanBal))),
dbo.DateOrNull(DateOfLastActivity),
LTRIM(RTRIM(LastActivityCode)),
dbo.DateOrNull(LTRIM(RTRIM(NextPaymentDueDate))),
dbo.ReplaceNonNumericDecimal(LTRIM(RTRIM(AccruedInt))),
dbo.ReplaceNonNumericDecimal(LTRIM(RTRIM(CreditLimit))),
LTRIM(RTRIM(SSN)),
dbo.ReplaceNonNumericInt(LTRIM(RTRIM(DaysDelinq)),'DaysDelinq','L'),
dbo.ReplaceNonNumericInt(LTRIM(RTRIM(Delinq30_59)),'Delinq30_59','L'),
dbo.ReplaceNonNumericInt(LTRIM(RTRIM(Delinq60_89)),'Delinq60_89','L'),
dbo.ReplaceNonNumericInt(LTRIM(RTRIM(Delinq90_119)),'Delinq90_119','L'),
dbo.ReplaceNonNumericInt(LTRIM(RTRIM(Delinq120_plus)),'Delinq120_plus','L'),
LTRIM(RTRIM(InsiderCode)),
LTRIM(RTRIM(LoanOfficer_CCInit)),
dbo.ReplaceNonNumericInt(LTRIM(RTRIM(CreditScore)),'CreditScore','L'),
dbo.ReplaceNonNumericDecimal(LTRIM(RTRIM(ChargeOffAmt))),
LTRIM(RTRIM(LoanRiskGrade)),
dbo.ReplaceNonNumericInt(LTRIM(RTRIM(RemainingPayments)),'RemainingPayments','L'),
LTRIM(RTRIM(LoanCollateralCode)),
dbo.DateOrNull((RTRIM(LastFileMaintDate))),
LTRIM(RTRIM(LastFileMaintUser)),
LTRIM(RTRIM(BranchId))
FROM #tmpLoan
DROP TABLE #tmpLoan
有没有办法做我想做的事情?
答案 0 :(得分:1)
在SQL中,函数必须像真函数一样(即没有副作用)。没有其他方法可以在列表达式中获取每行调用,因此您将不得不采用不同的方法。
有许多不同的方法可以获得你想要获得的东西,SSIS是这个的规范工具,但是从你已经到达的最短路径可能分两步完成:
扫描临时表以查找列转换中的任何异常,从临时表中删除这些行并将其记录到错误日志表中。
然后,执行上面的命令复制并转换剩余的所有行和列,而不尝试检查/验证它们(您已在第一步中完成了这一操作)。
值得一提的是,在T-SQL中,用户定义的标量函数的性能非常差,因此如果要导入大量行,那么您可能需要考虑使用表值函数。