ব্যবহারকারীদের সংজ্ঞায়িত টেবিল প্রকারের সাথে sp_executesql সঠিকভাবে আচরণ করছে না


11

সমস্যা : sp_executesql এর প্যারামিটার হিসাবে ব্যবহারকারী সংজ্ঞায়িত টেবিল প্রকারগুলির সাথে একটি জ্ঞাত সমস্যা আছে ? উত্তর - না, আমি একজন বোকা।

স্ক্রিপ্ট সেট আপ করুন

এই স্ক্রিপ্টটি প্রতিটি টেবিল, পদ্ধতি এবং ব্যবহারকারীর সংজ্ঞায়িত সারণী প্রকারের তৈরি করে (কেবলমাত্র এসকিউএল সার্ভার 2008+ কেবলমাত্র)।

  • গাদাটির উদ্দেশ্য হ'ল ডেটা প্রক্রিয়াটিতে তৈরি করে এমন একটি নিরীক্ষণ সরবরাহ করা। কোনও সীমাবদ্ধতা নেই, ডেটা beingোকানো থেকে রোধ করার জন্য কিছুই নেই।

  • পদ্ধতিটি ব্যবহারকারীকে সংজ্ঞায়িত টেবিল ধরণের পরামিতি হিসাবে গ্রহণ করে। সমস্ত প্রকল্পগুলি টেবিলের মধ্যে .োকানো হয়।

  • ব্যবহারকারীর সংজ্ঞায়িত টেবিল প্রকারটিও বোগ সহজ, কেবল একটি একক কলাম

আমি নীচে নিম্নলিখিতটি চালিয়েছি 11.0.1750.32 (X64) এবং 10.0.4064.0 (X64)হ্যাঁ, আমি জানি যে বাক্সটি প্যাচ করা যেতে পারে, আমি এটি নিয়ন্ত্রণ করি না।

-- this table record that something happened
CREATE TABLE dbo.UDTT_holder
(
    ServerName varchar(200)
,   insert_time datetime default(current_timestamp)
)
GO

-- user defined table type transport mechanism
CREATE TYPE dbo.UDTT
AS TABLE
(
    ServerName varchar(200)
)
GO

-- stored procedure to reproduce issue
CREATE PROCEDURE dbo.Repro
(
    @MetricData dbo.UDTT READONLY
)
AS
BEGIN
    SET NOCOUNT ON

    INSERT INTO dbo.UDTT_holder 
    (ServerName)
    SELECT MD.* FROM @MetricData MD
END
GO

সমস্যা পুনরুত্পাদন

এই স্ক্রিপ্টটি সমস্যাটি দেখায় এবং এটি কার্যকর করতে পাঁচ সেকেন্ড সময় নেওয়া উচিত। আমি আমার ব্যবহারকারীর সংজ্ঞায়িত টেবিল প্রকারের দুটি উদাহরণ তৈরি করি এবং তারপরে এগুলিকে পাস করার জন্য দুটি ভিন্ন উপায় চেষ্টা করি sp_executesql। প্রথম অনুরোধে প্যারামিটার ম্যাপিং আমি এসকিউএল প্রোফাইলার থেকে ক্যাপচার করেছি তা নকল করে। আমি তখন sp_executesqlমোড়ক ছাড়াই পদ্ধতিটি কল করি ।

SET NOCOUNT ON
DECLARE 
    @p3 dbo.UDTT
,   @MetricData dbo.UDTT
INSERT INTO @p3 VALUES(N'SQLB\SQLB')
INSERT INTO @MetricData VALUES(N'SQLC\SQLC')

-- nothing up my sleeve
SELECT * FROM dbo.UDTT_holder

SELECT CONVERT(varchar(24), current_timestamp, 121) + ' Firing sp_executesql' AS commentary
-- This does nothing
EXECUTE sp_executesql N'dbo.Repro',N'@MetricData dbo.UDTT READONLY',@MetricData=@p3
-- makes no matter if we're mapping variables
EXECUTE sp_executesql N'dbo.Repro',N'@MetricData dbo.UDTT READONLY',@MetricData

-- Five second delay
waitfor delay '00:00:05'
SELECT CONVERT(varchar(24), current_timestamp, 121) + ' Firing proc' AS commentary
-- this does
EXECUTE dbo.Repro @p3

-- Should only see the latter timestamp
SELECT * FROM dbo.UDTT_holder

GO

ফলাফল : নীচে আমার ফলাফল। টেবিলটি প্রাথমিকভাবে খালি। আমি বর্তমান সময় নির্গত করি এবং দুটি কল করি sp_executesql। আমি 5 সেকেন্ড অপেক্ষা করতে পারি এবং বর্তমান সময় নির্গত করতে সঞ্চিত প্রক্রিয়াটি নিজে কল করে এবং শেষ পর্যন্ত নিরীক্ষার টেবিলটি ফেলে রাখি।

আপনি যেমন টাইমস্ট্যাম্প থেকে দেখতে পাচ্ছেন, বি রেকর্ডের জন্য রেকর্ডটি স্ট্রেড স্টোরেজ পদ্ধতির অনুরোধের সাথে মিলে যায়। এছাড়াও, কোনও এসকিউএলসি রেকর্ড নেই।

ServerName                                       insert_time
------------------------------------------------------------------------

commentary
-------------------------------------------------
2012-02-02 13:09:05.973 Firing sp_executesql

commentary
-------------------------------------------------
2012-02-02 13:09:10.983 Firing proc

ServerName                                       insert_time
------------------------------------------------------------------------
SQLB\SQLB                                        2012-02-02 13:09:10.983

লিপি ছিঁড়ে ফেলুন

এই স্ক্রিপ্টটি সঠিক ক্রমে অবজেক্টগুলি সরিয়ে ফেলবে (পদ্ধতির উল্লেখটি সরানোর আগে আপনি টাইপটি ফেলে দিতে পারবেন না)

-- cleanup
DROP TABLE dbo.UDTT_holder
DROP PROCEDURE dbo.Repro
DROP TYPE dbo.UDTT
GO

কেন এটি গুরুত্বপূর্ণ

কোডটি নির্বোধ বলে মনে হচ্ছে তবে প্রো-প্রোকে একটি "সরাসরি" কল বনাম sp_execute ব্যবহারের উপর আমার খুব বেশি নিয়ন্ত্রণ নেই। কল চেইন উচ্চতর করুন, আমি ADO.NET গ্রন্থাগারটি ব্যবহার করছি এবং আমি আগের মতো একটি টিভিপিতে পাস করছি । পরামিতি ধরন সঠিকভাবে সেট করা হয় System.Data.SqlDbType.Structured এবং CommandType সেট করা হয় System.Data.CommandType.StoredProcedure

আমি কেন নুব (সম্পাদনা)

রব এবং মার্টিন স্মিথ যা দেখেছিলাম তা দেখেছি - sp_executesql এ দেওয়া বিবৃতিটি @MetricDataপ্যারামিটারটি ব্যবহার করে নি । একটি আনপাস করা / ম্যাপ করা প্যারামিটার ব্যবহার হতে যাচ্ছে না।

আমি আমার ওয়ার্কিং সি # টেবিলের মূল্যবান-পরামিতি কোডটি পাওয়ারশেলের সাথে অনুবাদ করছিলাম এবং যেহেতু এটি সংকলিত হয়েছে, এটি কোডটি ভুল হতে পারে না ; এটা ছাড়া। এই প্রশ্নের আপ লেখার সময়, আমি উপলব্ধি আমি লাগাই নি CommandTypeকরার StoredProcedureতাই আমি যে লাইন যোগ এবং কোড পুনরায় দৌড়ে কিন্তু তাই আমি অনুমান যে সমস্যা ছিল না প্রোফাইলার মধ্যে ট্রেস পরিবর্তন হয়নি।

মজার গল্প - আপনি যদি আপডেট হওয়া ফাইলটি সংরক্ষণ না করেন, এটি চালানো কোনও তাত্পর্যপূর্ণ করবে না। আমি এই সকালে পেয়েছি এবং এটি পুনরায় চালিত করেছি (সংরক্ষণের পরে) এবং ADO.NET এটি অনুবাদ করেছে EXEC dbo.Repro @MetricData=@p3যা ঠিক কাজ করে।

উত্তর:


10

sp_executesqlঅ্যাড-হক টি-এসকিউএল কার্যকর করার জন্য। সুতরাং আপনার চেষ্টা করা উচিত:

EXECUTE sp_executesql N'exec dbo.Repro @MetricData',N'@MetricData dbo.UDTT READONLY',@MetricData=@p3

1
+1 বর্তমানে ওপি-র স্ক্রিপ্টটিতে কেবল বিবৃতি রয়েছে dbo.Reproএবং প্যারামিটারগুলিতে পাস করা মোটেও ব্যবহার করে না।
মার্টিন স্মিথ

হ্যাঁ এসএসএস, আমি রবের মন্তব্য দেখেছি এবং এটিতে সেখানে এক্সইসি অংশের প্রয়োজন নেই, এটি বুঝতে পারা যায় যে কলটির সাথে প্যারামিটারটি ব্যবহার করা হচ্ছে না কারণ স্ক্রিপ্টটিতে প্যারামিটারটি উল্লেখ করা হয়নি। আমার মূর্খতা প্রতিফলিত করার জন্য টিকিট আপডেট করা হচ্ছে
বিলিংক

@ বিলিংক - আহ আমি আরও বিস্তারিত ব্যাখ্যা সহ একটি উত্তর যুক্ত করেছি তারপরে আপনার মন্তব্যটি দেখেছি। আমি উত্তরটি কিছুক্ষণের মধ্যে মুছে ফেলব।
মার্টিন স্মিথ

ঠিক। আপনি অ্যাডো নেট থেকে এটি করছেন বলে উল্লেখ করেননি। sp_executesql একটি .কমটেক্সট এর সমতুল্য, স্টোরপ্রসেসর নয়।
রব ফারলে 21

3

আমি এই প্রশ্নটি মুছে ফেলার জন্য প্রলুব্ধ হয়েছিলাম তবে অনুভূত হয়েছিল যে অন্য কেউ হয়তো একই পরিস্থিতিতে চলে যেতে পারে।

মূল কারণটি হ'ল আমার $updateCommandকমান্ডটাইপ সেট করা হয়নি। ডিফল্ট মানটি পাঠ্য তাই আমার সঞ্চিত পদ্ধতিটি সঠিকভাবে বলা হচ্ছে called আমার প্যারামিটারগুলি তৈরি এবং পাস করা হচ্ছিল তবে প্যারামিটারগুলি উপলভ্য হওয়ায় কেবলমাত্র অন্যান্য উত্তরে উল্লিখিত হয়েছে তার অর্থ এই নয় যে সেগুলি ব্যবহৃত হচ্ছে ।

কোড যদি কেউ আমার ভুলতে আগ্রহী ছিল

    $updateConnection = New-Object System.Data.SqlClient.SqlConnection("Data Source=localhost\localsqla;Initial Catalog=baseline;Integrated Security=SSPI;")
    $updateConnection.Open()

    $updateCommand = New-Object System.Data.SqlClient.SqlCommand($updateQuery)
    $updateCommand.Connection = $updateConnection

    # This is what I was missing
    $updateCommand.CommandType = [System.Data.CommandType]::StoredProcedure
    #$updateCommand.CommandType = [System.Data.CommandType]::Text
    #$updateCommand.CommandType = [System.Data.CommandType]::TableDirect

    $DataTransferFormat = $updateCommand.Parameters.AddWithValue("@MetricData", $dataTable)
    $DataTransferFormat.SqlDbType = [System.Data.SqlDbType]::Structured
    $DataTransferFormat.TypeName = $udtt
    $results = $updateCommand.ExecuteNonQuery()

কমান্ড টাইপের পাঠ্যের মান নিয়ে চলার জন্য @ রোবফারলির $updateQuery"এক্সেক ডিবিও.প্রি @ মেট্রিকডাটা" এর মান পরিবর্তন করার সমাধান প্রয়োজন । সেই সময়ে, sp_executesql মানগুলি সঠিকভাবে মানচিত্র করবে এবং জীবন ভাল good

একটি দিয়ে চলছে CommandTypeএর TableDirect, SqlClient ডেটা প্রদানকারীর দ্বারা সমর্থিত নয় ডকুমেন্টেশন ইঙ্গিত করা হয়।

একটি ব্যবহার CommandTypeএর StoredProcedureছাড়া সঞ্চিত পদ্ধতি সরাসরি আবাহন অনুবাদ sp_executesqlমোড়কের এবং কাজ করে মহান।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.