Có một trình điều khiển thực sự hỗ trợ TVPs: Pytds . Nó không được hỗ trợ chính thức, nhưng có cách triển khai phương ngữ của bên thứ 3 cho nó: sqlalchemy-pytds . Sử dụng chúng, bạn có thể gọi thủ tục được lưu trữ của mình như sau:
In [1]: engine.execute(DDL("CREATE TYPE [dbo].[StringTable] AS TABLE([strValue] [nvarchar](max) NULL)"))
Out[1]: <sqlalchemy.engine.result.ResultProxy at 0x7f235809ae48>
In [2]: engine.execute(DDL("CREATE PROC test_proc (@pArg [StringTable] READONLY) AS BEGIN SELECT * FROM @pArg END"))
Out[2]: <sqlalchemy.engine.result.ResultProxy at 0x7f2358027b70>
In [3]: arg = ['Name One', 'Name Two']
In [4]: import pytds
In [5]: tvp = pytds.TableValuedParam(type_name='StringTable',
...: rows=((x,) for x in arg))
In [6]: engine.execute('EXEC test_proc %s', (tvp,))
Out[6]: <sqlalchemy.engine.result.ResultProxy at 0x7f294e699e10>
In [7]: _.fetchall()
Out[7]: [('Name One',), ('Name Two',)]
Bằng cách này, bạn có thể chuyển một lượng lớn dữ liệu tiềm năng dưới dạng tham số:
In [21]: tvp = pytds.TableValuedParam(type_name='StringTable',
...: rows=((str(x),) for x in range(100000)))
In [22]: engine.execute('EXEC test_proc %s', (tvp,))
Out[22]: <sqlalchemy.engine.result.ResultProxy at 0x7f294c6e9f98>
In [23]: _.fetchall()[-1]
Out[23]: ('99999',)
Mặt khác, nếu bạn đang sử dụng trình điều khiển không hỗ trợ TVP, bạn có thể khai báo một biến bảng , chèn các giá trị và chuyển nó làm đối số đến thủ tục của bạn:
In [12]: engine.execute(
...: """
...: DECLARE @pArg AS [StringTable];
...: INSERT INTO @pArg VALUES {placeholders};
...: EXEC test_proc @pArg;
...: """.format(placeholders=",".join(["(%s)"] * len(arg))),
...: tuple(arg))
...:
Out[12]: <sqlalchemy.engine.result.ResultProxy at 0x7f23580f2908>
In [15]: _.fetchall()
Out[15]: [('Name One',), ('Name Two',)]
Lưu ý rằng bạn không thể sử dụng bất kỳ phương thức thực thi nào, nếu không bạn sẽ phải gọi thủ tục cho từng giá trị bảng riêng biệt. Đó là lý do tại sao các trình giữ chỗ được tạo theo cách thủ công và các giá trị bảng được truyền dưới dạng các đối số riêng lẻ. Cần phải chú ý không định dạng bất kỳ đối số nào trực tiếp trong truy vấn mà thay vào đó là số lượng trình giữ chỗ chính xác cho DB-API. Giá trị hàng được giới hạn ở tối đa là 1000 .
Tất nhiên sẽ rất tốt nếu trình điều khiển DB-API bên dưới cung cấp hỗ trợ thích hợp cho các tham số có giá trị của bảng, nhưng ít nhất tôi không thể tìm ra cách cho pymssql, sử dụng FreeTDS. tham chiếu đến TVP trong danh sách gửi thư nói rõ rằng chúng không được hỗ trợ. Tình hình là không tốt hơn cho PyODBC .
Tuyên bố từ chối trách nhiệm:Tôi chưa thực sự sử dụng MS SQL Server trước đây.