39

Cơ sở dữ liệu: Sybase Advantage 11Làm thế nào để viết câu lệnh SQL DELETE với câu lệnh SELECT trong mệnh đề WHERE?

Ngày quest của tôi để chuẩn hóa dữ liệu, tôi đang cố gắng để xóa các kết quả tôi nhận được từ tuyên bố SELECT này:

SELECT tableA.entitynum 
FROM tableA q 
INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR q.memotext NOT LIKE '%/%/%') 
AND (u.FldFormat = 'Date') 
; 

Đây là tuyên bố DELETE tôi đã đưa ra:

DELETE FROM tableA 
WHERE (SELECT q.entitynum 
FROM tableA q 
INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR q.memotext NOT LIKE '%/%/%') 
AND (u.FldFormat = 'Date')) 
; 

tôi liên tục nhận được lỗi này khi tôi cố gắng chạy tuyên bố này:

ERROR IN SCRIPT: poQuery: Error 7200: AQE Error: State = S0000; NativeError = 2124; 
[iAnywhere Solutions][Advantage SQL Engine]Invalid operand for operator: = Boolean value 
cannot be operated with non-Boolean value. 

Tôi cũng đã cố gắng tuyên bố này:

DELETE FROM tableA 
INNER JOIN tableB u on (u.qlabel = tableA.entityrole AND u.fieldnum = tableA.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR tableA.memotext NOT LIKE '%/%/%') 
AND (u.FldFormat = 'Date') 
; 

mà kết quả trong:

ERROR IN SCRIPT: poQuery: Error 7200: AQE Error: State = 42000; NativeError = 2117; 
[iAnywhere Solutions][Advantage SQL Engine] Unexpected token: INNER -- Expecting semicolon. 
-- Location of error in the SQL statement is: 23 (line: 2 column: 1) 

Có thể ai đó giúp tôi trong việc xây dựng đúng một truy vấn DELETE mà sẽ cho kết quả trong các dữ liệu thích hợp đang được gỡ bỏ?

+0

kịch bản Trường hợp xấu nhất - bạn có thể tạo ra một bảng tạm thời, CHỌN vào đó bảng tạm thời, làm xóa của bạn tham gia vào bảng tạm thời, sau đó droping bảng tạm thời? –

Trả lời

73

Bạn cần xác định khóa chính trong TableA để xóa bản ghi chính xác. Khóa chính có thể là một cột đơn hoặc kết hợp một số cột xác định duy nhất một hàng trong bảng. Nếu không có khóa chính, thì cột giả ROWID có thể được sử dụng làm khóa chính.

DELETE FROM tableA 
WHERE ROWID IN 
    (SELECT q.ROWID 
    FROM tableA q 
     INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
    WHERE (LENGTH(q.memotext) NOT IN (8,9,10) OR q.memotext NOT LIKE '%/%/%') 
     AND (u.FldFormat = 'Date')); 
+0

Cảm ơn Alex vì đã trả lời nhanh. @ AlexW Tôi nghĩ rằng bạn nhấn móng tay trên đầu. Cách mà bảng này hoạt động là thực thể có liên quan đến nhiều bản ghi và do đó không phải là khóa chính trong và của chính nó. Tôi không có kinh nghiệm với việc sử dụng các puedocolumn ROWID trong Advantage. Bạn có thể cung cấp giải thích về cách sử dụng này? Cảm ơn một lần nữa. – LuiCami

+0

Cảm ơn bạn @ AlexW Điều này đã làm việc tuyệt vời !! – LuiCami

9

nên không bạn có:

DELETE FROM tableA WHERE entitynum IN (...your select...) 

Bây giờ bạn chỉ có một WHERE không có so sánh:

DELETE FROM tableA WHERE (...your select...) 

Vì vậy, câu hỏi cuối cùng của bạn sẽ trông như thế này;

DELETE FROM tableA WHERE entitynum IN (
    SELECT tableA.entitynum FROM tableA q 
    INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
    WHERE (LENGTH(q.memotext) NOT IN (8,9,10) OR q.memotext NOT LIKE '%/%/%') 
    AND (u.FldFormat = 'Date') 
) 
+0

cảm ơn bạn đã phản hồi.Nó có vẻ như là khi tôi chạy một số những gì tôi sẽ xóa tôi kết thúc với nhiều hồ sơ nhiều hơn dự định ban đầu (4598021 thay vì 32061). Tôi chắc chắn đã đạt được trình độ chuyên môn của mình về điều này. Bạn có biết lý do này sẽ là trường hợp? Câu lệnh đếm của tôi trông như thế này: SELECT COUNT (*) FROM tableA WHERE entitynum IN (SELECT q.entitynum FROM tableA q INNER JOIN tableB u trên (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) WHERE (LENGTH (q.memotext) NOT IN (8,9,10) HOẶC q.memotext NOT LIKE '% /% /%') AND (u.FldFormat = 'Date')); – LuiCami

3

trong kịch bản này:

DELETE FROM tableA 
WHERE (SELECT q.entitynum 
FROM tableA q 
INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR q.memotext NOT LIKE '%/%/%') 
AND (u.FldFormat = 'Date')); 

không bạn thiếu cột bạn muốn so sánh với? ví dụ:

DELETE FROM tableA 
WHERE entitynum in (SELECT q.entitynum 
FROM tableA q 
INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR q.memotext NOT LIKE '%/%/%') 
AND (u.FldFormat = 'Date'));  

Tôi giả sử đó là cột đó trong câu lệnh chọn bạn đang chọn từ cùng một bảng bạn muốn xóa khỏi cột đó.

+0

cảm ơn bạn đã phản hồi. Nó có vẻ như là khi tôi chạy một số những gì tôi sẽ xóa tôi kết thúc với nhiều hồ sơ nhiều hơn dự định ban đầu (4598021 thay vì 32061). Tôi chắc chắn đã đạt được trình độ chuyên môn của mình về điều này. Bạn có biết lý do này sẽ là trường hợp? Câu lệnh đếm của tôi trông giống như sau: SELECT COUNT (*) FROM tableA WHERE entitynum IN (SELECT q.entitynum FROM tableA q ĐỐI TÁC BẢNG BÊN TRONG u u (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) WHERE (LENGTH (q.memotext) KHÔNG IN (8,9,10) HOẶC q.memotext KHÔNG THÍCH '% /% /%') VÀ (u.FldFormat = 'Date')) ; – LuiCami

+0

lựa chọn này cung cấp cho bạn các giá trị chính xác cần xóa? – Andres

+0

Số lượng lớn chắc chắn là có thể nếu entitynum không phải là duy nhất (hoặc khóa chính) trong TableA. Ví dụ Fore, có thể có một số hàng với entitynum bằng 1 nhưng chỉ một trong số chúng khớp với điều kiện kết nối. Tuy nhiên, điều kiện 'entitynum IN (SELECT ...)' sẽ trả về tất cả các hàng có entitynum bằng 1. –

1

Did một cái gì đó như thế một lần:

CREATE TABLE exclusions(excl VARCHAR(250)); 
INSERT INTO exclusions(excl) 
VALUES 
     ('%timeline%'), 
     ('%Placeholders%'), 
     ('%Stages%'), 
     ('%master_stage_1205x465%'), 
     ('%Accessories%'), 
     ('%chosen-sprite.png'), 
('%WebResource.axd'); 
GO 
CREATE VIEW ToBeDeleted AS 
SELECT * FROM chunks 
     WHERE chunks.file_id IN 
     (
     SELECT DISTINCT 
      lf.file_id 
     FROM LargeFiles lf 
     WHERE lf.file_id NOT IN 
      (
      SELECT DISTINCT 
        lf.file_id 
      FROM LargeFiles lf 
       LEFT JOIN exclusions e ON(lf.URL LIKE e.excl) 
       WHERE e.excl IS NULL 
      ) 
     ); 
GO 
CHECKPOINT 
GO 
SET NOCOUNT ON; 
DECLARE @r INT; 
SET @r = 1; 
WHILE @r>0 

BEGIN 
    DELETE TOP (10000) FROM ToBeDeleted; 
    SET @r = @@ROWCOUNT 
END 
GO 
4

tôi tinh chỉnh truy vấn thứ 2 của bạn để làm cho nó hoạt động. Tôi nghĩ điều này đơn giản hơn việc sử dụng câu lệnh lồng nhau SELECT như trong các câu trả lời khác.

DELETE q 
FROM tableA q 
INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR q.memotext NOT LIKE '%/%/%') 
AND (u.FldFormat = 'Date') 

Xem chi tiết ở đây:
How to Delete using INNER JOIN with SQL Server?