2009-07-21 10 views
8

Tôi cần chuyển đổi một lượng lớn truy vấn SQL thành các thủ tục được lưu trữ. Tôi có một số mã cập nhật khoảng 20 hoặc 30 giá trị cùng một lúc trong một thủ tục Delphi. Tôi có thể xử lý việc tạo một thủ tục được lưu trữ để làm một điều như vậy. Vấn đề là cách của tôi để truyền tham số cho thủ tục lưu trữ là rất cồng kềnh như thế này:Cách tốt hơn để truyền tham số cho TADOStoredProc (Delphi)

with stored_procedure do...... 
    Param := Parameters.AddParameter; 
    Param.Name := '@SSN'; 
    Param.Value := edtSSN.text; 

    Param := Parameters.AddParameter; 
    Param.Name := '@FirstName'; 
    Param.Value := edtFirstName.Text; 

    Param := Parameters.AddParameter; 
    Param.Name := '@LastName'; 
    Param.Value := edtLastName.Text; 

    Param := Parameters.AddParameter; 
    Param.Name := '@UserRID'; 
    Param.Value:= GetRIDFromCombo(cbUser); 

Tôi cũng không chắc chắn nếu nó gây ra rò rỉ bộ nhớ (là nó cần thiết để giải phóng đối tượng TParameter như vậy?)

Bất cứ ai có một cách tốt hơn để xử lý một số lượng lớn các thông số? (Tôi không thể sử dụng thư viện mới. Tôi phải sử dụng ADO và SQL tôi sử dụng là MSSQL) (cũng được, tôi KHÔNG sử dụng ADO.net)

Trả lời

11

Điều này không gây rò rỉ bộ nhớ. archive_procedure sẽ dọn sạch các tham số của nó. Bạn có thể xác nhận điều này bằng FastMM bằng cách thêm thông tin sau vào tệp .dpr:

ReportMemoryLeaksOnShutdown := True; 

Trước tiên, tôi muốn loại bỏ câu lệnh "có". Nó có thể dẫn đến nhiều vấn đề hơn và ít mã dễ đọc hơn.

Tôi muốn tạo phương thức trợ giúp chấp nhận quy trình được lưu trữ, tên thông số và giá trị tham số, điều này sẽ làm cho mã của bạn dễ quản lý hơn.

AddParam(stored_procedure, '@SSN', edtSSN.text); 
AddParam(stored_procedure, '@FirstName', edtFirstName.Text); 
AddParam(stored_procedure, '@LastName', edtLastName.Text); 
AddParam(stored_procedure, '@UserRID', GetRIDFromCombo(cbUser)); 
19

Có một câu trả lời chấp nhận :-), nhưng tôi muốn chỉ cho bạn cách đơn giản và dễ dàng hơn để xác định và sử dụng các thông số với một dòng:

stored_procedure.Parameters.CreateParameter('SSN',ftString,pdInput,30,edtSSN.text); 

Nó đơn giản và linh hoạt, bởi vì bạn có thể xác định các tham số đầu vào và đầu ra với cùng một dòng.

và từ Delphi giúp đỡ:

function CreateParameter(const Name: WideString; DataType: TDataType; 
    Direction: TParameterDirection; Size: Integer; 
    Value: OleVariant): TParameter; 
+2

này dường như là một câu trả lời tốt hơn so với tôi. –

+0

Tôi không biết rằng đã tồn tại. Cám ơn vì đã chia sẻ! – robsoft

+0

Cảm ơn Bruce & Rob, Đó là vẻ đẹp của SO, tôi đã học được nhiều điều cho Delphier ở đây, và cố gắng chia sẻ những gì tôi biết với người khác :-) –

10

ADO sẽ tạo ra các thông số cho bạn, bạn chỉ cần gọi Refresh trên các thông số đối tượng:

SP.Connection := SqlConnection; // must be done before setting procedure name 
sp.ProcedureName := 'MyStoredProc'; 
sp.Parameters.Refresh; // This will create the parameters for you as defined in SQL Server 
sp.Parameters.ParamByName('@SSN'').Value := SSN; // params now exist 

vv

Nếu bất kỳ thông số là đầu ra, bạn sẽ cần phải đặt chúng rõ ràng:

sp.Parameters.ParamByName('@ReturnValue').Direction := pdInputOutput; 
+1

Điều này là tốt đẹp nhưng nó chỉ hoạt động nếu thủ tục nằm trong cơ sở dữ liệu mặc định của kết nối. Có một lỗi trong ADO phá hủy các tham số nếu bạn sử dụng DifferentDatabase.Owner.ProcedureName – DiGi

+1

Tôi cũng thấy rằng .Refresh không phải lúc nào cũng hoạt động, ngay cả trong cùng một database.owner. Tôi đã không tìm thấy bất kỳ mẫu nào khi nó hoạt động và khi nó không hoạt động, nhưng khi nó không nhận được và lỗi như "Parameter" @SearchText 'không tìm thấy."Khi tôi sử dụng .ParamByName. Cuộc gọi tương tự đó hoạt động 99,9% thời gian. Thêm thông số theo cách thủ công có vẻ bỏ qua vấn đề. – Tony

0

Đây là ngắn nhất tôi biết:

stored_procedure.Parameters.ParamByName('@SSN').Value := edtSSN.text; 

Lưu ý, bạn cần gán stored_procedure.Connection và gọi stored_procedure.Parameters.Refresh; trước khi làm điều này