将nvarchar转换为日期时间时的异常

问题描述 投票:0回答:1

我在SQL Server 2014中具有此存储过程,基本上,如果第二个表中不存在该数据,则该数据将从一个表复制到另一个表。复制时,它必须进行一些转换,因为第一个表中的所有列均为nvarchar。几乎每次执行此过程时,都会出现转换错误:

将nvarchar数据类型转换为datetime数据类型导致值超出范围。

我插入了try-catch指令来获取错误,但并没有太大帮助。另外,我决定使用辅助变量(@aux),以帮助我检查错误发生在过程的哪一点,因为我无权在SSMS上调试过程。

我认为由于日期格式或文化原因,我收到此错误。我的第一个表中确实有行,其日期类似于'00 -00-0000',这就是为什么它是varchar的原因,并且在复制过程中我在程序中也执行了IF语句来替换它们。

这是我的程序:

BEGIN try
    DECLARE crPESSOA_MKT CURSOR FOR
        SELECT DISTINCT 
            cpf, nome, nascimento, sexo, endereco, numero, complemento, 
            bairro, cidade, estado, cep, email, telefone, celular, receber_emails, qtde_codigos 
        FROM dbo.CLIENTESMKT2019 
        WHERE cpf IS NOT NULL

    DECLARE @Cpf nvarchar(255), @nome nvarchar(255), @nascimento datetime, 
            @sexo nvarchar(255), @endereco nvarchar(255), @numero nvarchar(255), 
            @complemento nvarchar(255), @bairro nvarchar(255), @cidade nvarchar(255), 
            @estado nvarchar(255), @cep nvarchar(255), @email nvarchar(255), 
            @telefone nvarchar(255), @celular nvarchar(255), @receber_emails nvarchar(255), 
            @qtde_codigos float, @data_errada nvarchar(255), @aux varchar(50)

    OPEN crPESSOA_MKT

    SET @aux = 'open'

    FETCH NEXT FROM crPESSOA_MKT INTO @Cpf, @nome, @nascimento, @sexo, @endereco, @numero, @complemento, @bairro, @cidade, @estado, @cep, @email, @telefone, @celular, @receber_emails, @qtde_codigos

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @aux = CONCAT('while ',@nascimento)
        SET @nascimento = FORMAT(@nascimento, 'dd-MM-yyyy', 'pt-BR')
        SET @aux = CONCAT('nascimento = ', @nascimento)

        IF NOT EXISTS (SELECT PESSOA.CPF FROM PESSOA 
                       WHERE PESSOA.CPF = LEFT(CAST(@Cpf AS VARCHAR), 11))
        BEGIN
            SET @aux = 'if exists'

            IF ISDATE(@nascimento) = 0 OR 
               @nascimento = CAST('00-00-0000' AS DATE) OR 
               YEAR(@nascimento) < 1900
            BEGIN
                SET @aux = 'if isdate'
                SET @nascimento = CAST('01-01-1900' AS DATE)
                SET @aux = 'set @nascimento'
            END
            ELSE
            BEGIN
                SET @aux = 'else'
                SET @nascimento = CAST(@nascimento AS DATE)
                SET @aux = 'cast nascimento'
            END

            SET @data_errada = CAST(@nascimento AS NVARCHAR)
            SET @aux = 'errados'

            INSERT INTO dbo.PESSOA (CPF, NOME, ENDERECO, BAIRRO, CIDADE, CEP, COMPLEMENTO,
                                    EMAIL, DATA_NASCIMENTO, FONE, ESTADO, SEXO, 
                                    CELULAR, RECEBE_EMAILSN, QTD_CUPONS, NUMERO, IDORIGEM, DATA_INCLUSAO)
            VALUES (LEFT(@cpf, 11), LEFT(@nome, 50), LEFT(@endereco, 50), LEFT(@bairro, 50), LEFT(UPPER(@CIDADE), 50) COLLATE SQL_Latin1_General_CP1251_CS_AS, LEFT(@cep, 8), LEFT(@complemento, 50),
                    LEFT(@email, 50), @nascimento, LEFT(@telefone, 12), LEFT(@estado, 2), LEFT(@sexo, 1),
                    LEFT(@celular, 11), LEFT(@receber_emails, 1), @qtde_codigos, LEFT(CAST(@numero AS NVARCHAR), 15), 8, CURRENT_TIMESTAMP)

            SET @aux = 'insert'
        END
        /* ELSE
        BEGIN
            IF EXISTS (SELECT PESSOA.CPF FROM PESSOA 
                       WHERE PESSOA.CPF  = LEFT(CAST(@Cpf AS VARCHAR), 11))
            BEGIN
                SELECT EMAIL, LEFT(@email, 50) 
                FROM PESSOA 
                WHERE PESSOA.CPF = LEFT(CAST(@Cpf AS VARCHAR), 11)

                -- UPDATE PESSOA 
                -- SET EMAIL = LEFT(@email, 50)
                -- WHERE PESSOA.CPF  = LEFT(CAST(@Cpf AS VARCHAR), 11)
                --   AND EMAIL IS NULL
            END
        END*/      

        FETCH NEXT FROM crPESSOA_MKT INTO @Cpf, @nome, @nascimento,@sexo,@endereco,@numero,@complemento,@bairro,@cidade,@estado,@cep,@email,@telefone,@celular,@receber_emails,@qtde_codigos
        SET @aux = 'next'
    END

    CLOSE crPESSOA_MKT
    DEALLOCATE crPESSOA_MKT
END TRY
BEGIN CATCH
    SELECT  
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() AS ErrorState,
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_MESSAGE() AS ErrorMessage,
        @nascimento AS 'nascimento',
        @data_errada AS 'data errada',
        @aux AS 'aux'
END CATCH

这是我得到的结果:

enter image description here

编辑

这里是使我出错的寄存器之一。黄色值是我的日期列。即使它是'0000-00-00',执行IF语句时过程也不应更改它吗?enter image description here

sql-server datetime stored-procedures type-conversion nvarchar
1个回答
0
投票

此行出现错误->

FETCH NEXT FROM crPESSOA_MKT INTO @Cpf, @nome, @nascimento

[您正试图将'0000-00-00'形式的字符串强制放入DATETIME变量@nascimento中,这将导致无效的转换。

如果这是您要导入的数据中唯一的边缘情况,则作为变通方法,请检查有效性并将'000-00-00'转换为null,但我敢打赌,该值的目的还是要这样做。

SELECT DISTINCT 
     cpf, nome, CASE WHEN ISDATE(nascimento) THEN nascimento ELSE NULL END , sexo, endereco, numero, complemento, 
© www.soinside.com 2019 - 2024. All rights reserved.