17

Tôi đang cố gắng viết truy vấn này để tìm tất cả các bảng có cột cụ thể với một số giá trị cụ thể. Đây là những gì tôi đã thực hiện cho đến nay -SQL Server sp_msforeachtable usage để chỉ chọn những bảng đáp ứng một số điều kiện

EXEC sp_MSforeachtable 
@command1=' 
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=PARSENAME("?",2) AND TABLE_NAME=PARSENAME("?",1) AND COLUMN_NAME="EMP_CODE") 
BEGIN 
    IF (SELECT COUNT(*) FROM ? WHERE EMP_CODE="HO081")>0 
    BEGIN 
     SELECT * FROM ? WHERE EMP_CODE="HO081" 
    END 
END 
' 

Tôi hy vọng intensions của tôi rất rõ ràng, tôi chỉ muốn chỉ chọn những bảng nơi cột EMP_CODE là hiện tại và trong những bảng tôi muốn chọn những hàng nơi EMP_CODE='HO081' .

Edit -

Bây giờ nó đứng như thế này. Nhưng tôi không thể thay thế biến số @EMPCODE trong truy vấn.

DECLARE @EMPCODE AS VARCHAR(20) 
SET @EMPCODE='HO081' 
EXEC sp_MSforeachtable 
@command1=' 
    DECLARE @COUNT AS INT 
    SELECT @COUNT=COUNT(*) FROM ? WHERE EMP_CODE='''[email protected]+''' 
    IF @COUNT>0 
    BEGIN 
     PRINT PARSENAME("?",1)+'' => ''+CONVERT(VARCHAR,@COUNT)+'' ROW(S)'' 
     --PRINT ''DELETE FROM ''+PARSENAME("?",1)+'' WHERE EMP_CODE='''''[email protected]+''''''' 
    END 
',@whereand='AND O.ID IN (SELECT OBJECT_ID FROM SYS.COLUMNS C WHERE C.NAME='''[email protected]+''')' 

Trả lời

45

Bạn biết cách sp_MSforeachtable không có giấy tờ và có thể biến mất bất cứ lúc nào/sửa đổi? Vâng, nếu bạn vui lòng bỏ qua điều đó, nó có một tham số khác được gọi là @whereand, được thêm vào mệnh đề WHERE của truy vấn nội bộ đang được sử dụng để tìm các bảng (và nên bắt đầu bằng AND).

Bạn cũng phải biết rằng có một bí danh, o chống lại sysobjects và bí danh thứ hai syso chống lại sys.all_objects.

Sử dụng kiến ​​thức này, bạn có thể phác thảo tham số @whereand của bạn như:

EXEC sp_MSforeachtable 
@command1='...', 
@whereand='AND o.id in (select object_id from sys.columns c where c.name=''EMP_CODE'')' 

Bây giờ bạn cũng có thể đơn giản hóa command1 của bạn, vì bạn biết điều đó sẽ chỉ được chạy với các bảng có chứa một cột EMP_CODE. Tôi có lẽ sẽ đưa ra các điều kiện COUNT(*) cũng, vì tôi không thấy những gì giá trị nó thêm.


cập nhật dựa trên công việc tiếp theo của bạn, và thử nghiệm đối với một bảng:

DECLARE @EMPCODE AS VARCHAR(20) 
SET @EMPCODE='HO081' 
declare @sql nvarchar(2000) 
set @sql = ' 
    DECLARE @COUNT AS INT 
    SELECT @COUNT=COUNT(*) FROM ? WHERE EMP_CODE='''[email protected]+''' 
    IF @COUNT>0 
    BEGIN 
     PRINT PARSENAME("?",1)+'' => ''+CONVERT(VARCHAR,@COUNT)+'' ROW(S)'' 
     --PRINT ''DELETE FROM ''+PARSENAME("?",1)+'' WHERE EMP_CODE='''''[email protected]+''''''' 
    END 
' 
EXEC sp_MSforeachtable 
@[email protected],@whereand='AND O.ID IN (SELECT OBJECT_ID FROM SYS.COLUMNS C WHERE C.NAME=''EMP_CODE'')' 

(Tôi đã quay trở các @whereand để truy vấn cho EMP_CODE, vì bạn không muốn thay thế các giá trị có).

Vấn đề là, bạn có thể vượt qua thông số đến một thủ tục lưu trữ, hoặc literals, nhưng bạn không thể thực hiện các phép tính/kết hợp hành động giữa chúng - vì vậy tôi chuyển việc xây dựng báo cáo sql ra thành một hành động riêng biệt.

+4

+1 cho hiển thị cho bạn những gì bạn có thể làm, nhưng ngầm nói cho bạn để không làm điều đó;?) – cairnz

+0

@Damien_The_Unbeliever Giả sử nếu tôi viết 'IF (SELECT COUNT (*) FROM ĐÂU EMP_CODE = ''' + @EMPCODE + '' ')> 0' thì tại sao nó cho tôi - cú pháp không chính xác gần '+'. Tôi đang cố chuyển giá trị 'EMP_CODE' thông qua một biến. –

+0

@SohamDasgupta - Đó là một chút khó khăn để chẩn đoán loại vấn đề này trong phần ý kiến, vì tôi thực sự cần xem toàn bộ truy vấn vì nó bây giờ là viết tắt, và điều đó sẽ không hoạt động trong các bình luận. Tôi lại một lần nữa sẽ truy vấn đoạn mã cụ thể đó - tại sao * đếm * số hàng phù hợp thay vì chỉ chọn chúng? Các tập kết quả trống thường khá dễ giải quyết. –

9

Tôi đoán bạn gặp lỗi nào đó, có lẽ là Invalid column name 'EMP_CODE'?

Đó là vì mã được biên dịch trước khi bạn kiểm tra cột. Bạn có thể làm như thế này thay thế.

EXEC sp_MSforeachtable 
@command1=' 
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=PARSENAME("?",2) AND TABLE_NAME=PARSENAME("?",1) AND COLUMN_NAME="EMP_CODE") 
BEGIN 
    EXEC('' 
      IF (SELECT COUNT(*) FROM ? WHERE EMP_CODE="HO081")>0 
      BEGIN 
       SELECT * FROM ? WHERE EMP_CODE="HO081" 
      END 
     '') 
END 
' 
+0

Hoạt động tuyệt vời. Cảm ơn. –

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