从函数插入或使用T-SQL中的函数等存储过程

时间:2017-05-03 17:53:25

标签: sql-server tsql

我试图编写一个执行批量插入的程序,在这个批量插入中,我将所有未解析为正确数据类型的数据转换为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

有没有办法做我想做的事情?

1 个答案:

答案 0 :(得分:1)

在SQL中,函数必须像真函数一样(即没有副作用)。没有其他方法可以在列表达式中获取每行调用,因此您将不得不采用不同的方法。

有许多不同的方法可以获得你想要获得的东西,SSIS是这个的规范工具,但是从你已经到达的最短路径可能分两步完成:

  1. 扫描临时表以查找列转换中的任何异常,从临时表中删除这些行并将其记录到错误日志表中。

  2. 然后,执行上面的命令复制并转换剩余的所有行和列,而不尝试检查/验证它们(您已在第一步中完成了这一操作)。

  3. 值得一提的是,在T-SQL中,用户定义的标量函数的性能非常差,因此如果要导入大量行,那么您可能需要考虑使用表值函数。