Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

SQLAlchemy के साथ संग्रहीत कार्यविधि को कैसे कॉल करें जिसके लिए उपयोगकर्ता-परिभाषित-प्रकार तालिका पैरामीटर की आवश्यकता होती है

एक ड्राइवर है जो वास्तव में टीवीपी का समर्थन करता है:Pytds . यह आधिकारिक तौर पर समर्थित नहीं है, लेकिन इसके लिए एक तृतीय पक्ष बोली कार्यान्वयन है:sqlalchemy-pytds . उनका उपयोग करके आप अपनी संग्रहीत कार्यविधि को इस प्रकार कॉल कर सकते हैं:

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',)]

इस तरह आप संभावित रूप से बड़ी मात्रा में डेटा को पैरा के रूप में पास कर सकते हैं:

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',)

यदि दूसरी ओर आप ऐसे ड्राइवर का उपयोग कर रहे हैं जो TVP का समर्थन नहीं करता है, तो आप तालिका चर घोषित करें , मान डालें, और उसे तर्क के रूप में पारित करें आपकी प्रक्रिया के लिए:

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',)]

ध्यान दें कि आप किसी भी एक्ज़ीक्यूटमैनी विधियों का उपयोग नहीं कर सकते हैं, या आप प्रत्येक तालिका मान के लिए अलग से प्रक्रिया को कॉल करना समाप्त कर देंगे। यही कारण है कि प्लेसहोल्डर मैन्युअल रूप से बनाए जाते हैं और तालिका मान अलग-अलग तर्कों के रूप में पारित होते हैं। किसी भी तर्क को सीधे क्वेरी में प्रारूपित करने के लिए नहीं, बल्कि डीबी-एपीआई के लिए प्लेसहोल्डर्स की सही मात्रा का ध्यान रखा जाना चाहिए। पंक्ति मान एक अधिकतम 1000

यह निश्चित रूप से अच्छा होगा, यदि अंतर्निहित डीबी-एपीआई ड्राइवर ने तालिका मूल्यवान पैरामीटर के लिए उचित समर्थन प्रदान किया है, लेकिन कम से कम मुझे pymssql के लिए कोई रास्ता नहीं मिला, जो फ्रीटीडीएस का उपयोग करता है। एक मेलिंग सूची में टीवीपी का संदर्भ यह स्पष्ट करता है कि वे समर्थित नहीं हैं। स्थिति PyODBC के लिए बेहतर नहीं है

<उप>अस्वीकरण:मैंने पहले वास्तव में MS SQL सर्वर का उपयोग नहीं किया है।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. एसक्यूएल सर्वर ट्रिगर नई पंक्ति से दूसरी तालिका में मूल्यों को सम्मिलित करता है

  2. कन्वर्ट () SQL सर्वर में

  3. मैं एक बड़े बफर को बनाए बिना SQL सर्वर BLOB में .NET ऑब्जेक्ट का एक बड़ा ग्राफ कैसे क्रमबद्ध करूं?

  4. MS SQL सर्वर में लंबे समय से चल रहे प्रश्नों का समस्या निवारण

  5. एकाधिक स्तंभों के साथ SQL धुरी