2010-05-04 59 views
7

Microsoft SQL Server 2008 (SP1), nhận được lỗi 'Chuyển đổi không thành công' không mong muốn.Chuyển đổi không thành công khi chuyển đổi giá trị varchar thành int

Không hoàn toàn chắc chắn cách mô tả vấn đề này, vì vậy dưới đây là một ví dụ đơn giản. CTE trích xuất phần số của một số ID nhất định bằng cách sử dụng điều kiện tìm kiếm để đảm bảo một phần số thực sự tồn tại. CTE sau đó được sử dụng để tìm số thứ tự không sử dụng thấp nhất (loại):

CREATE TABLE IDs (ID CHAR(3) NOT NULL UNIQUE); 

INSERT INTO IDs (ID) VALUES ('A01'), ('A02'), ('A04'), ('ERR'); 

WITH ValidIDs (ID, seq) 
AS 
(
SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER) 
    FROM IDs 
    WHERE ID LIKE 'A[0-9][0-9]' 
) 
SELECT MIN(V1.seq) + 1 AS next_seq 
    FROM ValidIDs AS V1 
WHERE NOT EXISTS (
        SELECT * 
        FROM ValidIDs AS V2 
        WHERE V2.seq = V1.seq + 1 
       ); 

Lỗi này là 'Chuyển đổi không thành công khi chuyển giá trị varchar' RR 'sang kiểu dữ liệu int.'

Tôi không thể hiểu tại sao giá trị ID = 'ERR' phải được xem xét để chuyển đổi vì vị từ ID LIKE 'A[0-9][0-9]' nên đã xóa hàng không hợp lệ khỏi resultset.

Khi bảng cơ sở được thay thế bằng một CTE tương đương vấn đề đi xa ví dụ:

WITH IDs (ID) 
AS 
(
SELECT 'A01' 
UNION ALL 
SELECT 'A02' 
UNION ALL 
SELECT 'A04' 
UNION ALL 
SELECT 'ERR' 
), 
ValidIDs (ID, seq) 
AS 
(
SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER) 
    FROM IDs 
    WHERE ID LIKE 'A[0-9][0-9]' 
) 
SELECT MIN(V1.seq) + 1 AS next_seq 
    FROM ValidIDs AS V1 
WHERE NOT EXISTS (
        SELECT * 
        FROM ValidIDs AS V2 
        WHERE V2.seq = V1.seq + 1 
       ); 

Tại sao một bảng cơ sở gây ra lỗi này? Đây có phải là một vấn đề được biết đến?


Cập nhật @sgmoore: không, việc lọc trong một CTE và vẫn dẫn đến lỗi tương tự, ví dụ:

WITH FilteredIDs (ID) 
AS 
(
SELECT ID 
    FROM IDs 
    WHERE ID LIKE 'A[0-9][0-9]' 

), 
ValidIDs (ID, seq) 
AS 
(
SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER) 
    FROM FilteredIDs 
) 
SELECT MIN(V1.seq) + 1 AS next_seq 
    FROM ValidIDs AS V1 
WHERE NOT EXISTS (
        SELECT * 
        FROM ValidIDs AS V2 
        WHERE V2.seq = V1.seq + 1 
       ); 
+1

CTE lõi hoạt động tốt - hãy thử bằng cách sử dụng 'SELECT * FROM ValidIDs' thay vì truy vấn của bạn. Lỗi phải ở một nơi khác ... –

+0

@marc_s: Tôi đồng ý CTE không phải là nguồn gốc của vấn đề. Tôi không chắc chắn làm thế nào CTEs làm việc dưới bao gồm nhưng tôi hy vọng truy vấn của CTE chỉ đơn thuần là mở rộng ra các truy vấn tại thời gian phân tích cú pháp. Thật vậy, viết lại truy vấn bằng cách sử dụng hai bảng có nguồn gốc (mỗi bảng có cùng cú pháp chính xác) tất nhiên vẫn thể hiện vấn đề. – onedaywhen

Trả lời

3

Đó là một lỗi và đã được báo cáo là SQL Server should not raise illogical errors (như tôi đã nói, thật khó để diễn tả thế này!) bởi Erland Sommarskog.

Phản hồi từ Nhóm lập trình máy chủ SQL là, "vấn đề là SQL Server tăng lỗi [quá] háo hức do đẩy prediates/biểu thức trong quá trình truy vấn mà không xem xét kết quả logic của truy vấn."

bây giờ tôi đã bình chọn cho một sửa chữa, mọi người đều làm như vậy xin vui lòng :)

+0

Cũng có thể xảy ra trong Oracle bằng giao diện này https://stackoverflow.com/q/46287236/73226 –

0

gì nếu bạn thay thế phần

SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER) 
FROM IDs 
WHERE ID LIKE 'A[0-9][0-9]' 

Với

SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER) 
FROM 
(
    select ID from IDs 
    WHERE ID LIKE 'A[0-9][0-9]' 
) 
+0

Tôi gặp lỗi tương tự. Xem chỉnh sửa của tôi cho câu hỏi. – onedaywhen

+0

Rất lạ và tôi không hiểu nó. Lỗi có vẻ như trên dòng WHERE V2.seq = V1.seq + 1 thay đổi nó thành WHERE là số (v2.seq) = 1 và isnumeric (v1.seq) = 1 và V2.seq = V1. seq + 1 hoạt động (đối với tôi) – sgmoore

0

này xảy ra với tôi vì tôi đã làm một Union và đã không cẩn thận để đảm bảo cả hai truy vấn có lĩnh vực của họ theo thứ tự. Một khi tôi đã sửa nó, nó ổn.

Các vấn đề liên quan