क्या हम एसक्यूएल में एक दृश्य के मापदंडों को पारित कर सकते हैं?


138

क्या हम Microsoft SQL सर्वर में एक दृश्य के लिए एक पैरामीटर पारित कर सकते हैं?

मैंने create viewनिम्नलिखित तरीके से प्रयास किया, लेकिन यह काम नहीं करता है:

create or replace view v_emp(eno number) as select * from emp where emp_id=&eno;

एक दृश्य एक चयनित क्वेरी का एक संग्रहीत sql पाठ है। पैरामीटर चर्चा से बाहर हैं। जब आपकी संग्रहीत क्वेरी उस कॉलम को लौटा देती है जहाँ आप फ़िल्टर करना चाहते हैं, तो आप इसे कॉलिंग क्वेरी में कर सकते हैं। उदाहरण के लिए "चुनें * v_emp से कहाँ emp_id =?"
एपिकुरिस्ट

2
@Epicurist Parameters are out of the discussionबहुत बोल्ड बयान। काउंटरएक्सप्लांट
लुकाज़ स्ज़ोज़ा

जवाबों:


132

जैसा कि पहले ही कहा गया है कि आप नहीं कर सकते।

एक संभव समाधान संग्रहीत कार्य को कार्यान्वित करना होगा, जैसे:

CREATE FUNCTION v_emp (@pintEno INT)
RETURNS TABLE
AS
RETURN
   SELECT * FROM emp WHERE emp_id=@pintEno;

इससे आप इसे सामान्य दृश्य के रूप में उपयोग कर सकते हैं:

SELECT * FROM v_emp(10)

इस और एक दृश्य के बीच व्यावहारिक अंतर क्या हैं? क्या आप केवल इस फ़ंक्शन तक पहुँचने के लिए उपयोगकर्ता की अनुमति प्रदान कर सकते हैं?
मिकमर्कू

MySQL में आप एक संग्रहीत कार्यविधि लिखते हैं और इस प्रक्रिया में अंतिम विवरण देते हैं जो परिणाम आप चाहते हैं।
बोब्बोबो

क्या हम जावा में JDBC कोड से किसी भी समस्या के बिना उस अनुरोध का उपयोग कर सकते हैं?
मौनिम

@MikeMurko एक महत्वपूर्ण अंतर यह है कि किसी दृश्य के स्तंभों के बारे में स्कीमा / मेटाडेटा को एक दृश्य के रूप में देखा जा सकता है। यदि इसका संग्रहित प्रोक या कोई फ़ंक्शन है, तो मुझे लगता है कि डेटाबेस आपको वह जानकारी नहीं दे सकता है।
nagu

यदि आपके पास उन उपयोगकर्ताओं का एक समूह है, जिनके पास आपके डेटाबेस तक पहुँच है, और आप नहीं चाहते हैं कि वे "[देखें] से" का चयन करें और प्रदर्शन को प्रभावित करते हुए, आप कुछ कार्यों तक पहुँच प्रदान कर सकते हैं, जो उन्हें फ़िल्टर पैरामीटर प्रदान करने के लिए बाध्य करेगा। उदाहरण के लिए, सूचकांक का एक निश्चित सेट का लाभ उठाते हैं।
Jmoney38

35

आप क्या दुर्भाग्य से चाहते हैं और न ही एक दृश्य का उपयोग करके किया जा सकता है को प्राप्त करने के लिए 2 तरीके हैं।

आप या तो एक तालिका मान उपयोगकर्ता परिभाषित फ़ंक्शन बना सकते हैं जो आपके इच्छित पैरामीटर को लेता है और एक क्वेरी परिणाम देता है

या आप एक ही काम बहुत ज्यादा कर सकते हैं, लेकिन उपयोगकर्ता परिभाषित फ़ंक्शन के बजाय एक संग्रहीत कार्यविधि बनाएं।

उदाहरण के लिए

संग्रहीत प्रक्रिया की तरह दिखेगा

CREATE PROCEDURE s_emp
(
    @enoNumber INT
) 
AS 
SELECT
    * 
FROM
    emp 
WHERE 
    emp_id=@enoNumber

या उपयोगकर्ता परिभाषित फ़ंक्शन की तरह दिखेगा

CREATE FUNCTION u_emp
(   
    @enoNumber INT
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT    
        * 
    FROM    
        emp 
    WHERE     
        emp_id=@enoNumber
)

बस ध्यान रखें कि आप SELECTआसानी से SP विकल्प का उपयोग नहीं कर सकते हैं: अधिक पढ़ें
सायं

13

नहीं, आप नहीं कर सकते, जैसा कि म्लादेन प्राजिक ने कहा। किसी तालिका या तालिकाओं के संयोजन पर "स्थिर फ़िल्टर" के रूप में देखें। उदाहरण के लिए: एक दृश्य तालिकाओं को जोड़ सकता है Orderऔर Customerइसलिए आपको Orderग्राहक के नाम और ग्राहक संख्या (तालिकाओं के संयोजन) वाले नए स्तंभों के साथ पंक्तियों की एक नई "तालिका" मिलती है । या आप एक ऐसा दृश्य बना सकते हैं जो Orderतालिका (स्थिर फ़िल्टर) से केवल असंसाधित आदेशों का चयन करता है ।

फिर आप उस दृश्य से चयन करेंगे जैसे आप किसी अन्य "सामान्य" तालिका से चुनेंगे - सभी "नॉन-स्टैटिक" फ़िल्टरिंग को दृश्य के बाहर किया जाना चाहिए (जैसे "मिलर नामक ग्राहकों के सभी ऑर्डर प्राप्त करें" या "अनप्रोसेस्ड ऑर्डर प्राप्त करें" वह 24 दिसंबर को आया था))।


12

आम तौर पर विचारों को पैरामीटर नहीं किया जाता है। लेकिन आप हमेशा कुछ मापदंडों को इंजेक्ट कर सकते हैं। उदाहरण के लिए सत्र संदर्भ का उपयोग :

CREATE VIEW my_view
AS
SELECT *
FROM tab
WHERE num = SESSION_CONTEXT(N'my_num');

मंगलाचरण:

EXEC sp_set_session_context 'my_num', 1; 
SELECT * FROM my_view;

और दुसरी:

EXEC sp_set_session_context 'my_num', 2; 
SELECT * FROM my_view;

DBFiddle डेमो

वही ओरेकल के लिए लागू होता है (संदर्भ फ़ंक्शन के लिए वाक्यविन्यास अलग है)।


2
मुझे लगता है कि यह बहुत आसान है। जावा में वेब ऐप्स जैसे पैरामीटर कैसे पारित किए जा सकते हैं, इसके समान।

1
आसान और कार्यात्मक! दूसरे शब्दों में ... एकदम सही! धन्यवाद!
रिकार्डो बासीलीची

मैं थक गया। WHERE COUL = SESSION_CONTEXT (N'Ket ') जोड़ना; दृश्य में परिणाम 'त्रुटि SESSION_CONTEXT' एक मान्यता प्राप्त अंतर्निहित फ़ंक्शन नाम नहीं है।
user123456

@ user123456 आपको SQL Server 2016 और इसके बाद के संस्करण या Azure SQL डेटाबेस का उपयोग करना होगा
Lukasz Szozda

9

आपको दृश्य में एक पैरामीटर की आवश्यकता क्यों है? आप केवल WHEREखंड का उपयोग कर सकते हैं ।

create view v_emp as select * from emp ;

और आपकी क्वेरी को काम करना चाहिए:

select * from v_emp where emp_id=&eno;

11
कुछ मामलों में एक बड़ा प्रदर्शन सुधार होगा, जब यह दृश्य के WHEREबजाय तालिका के WHEREलिए है।
डग_इज़न

जबकि डौग जो कहता है वह कुछ हद तक सही है, आधुनिक डेटाबेस स्मार्ट तरीके से 'विस्तार' करने का एक उल्लेखनीय काम कर सकते हैं और प्रभावी रूप से उसी परिणाम के साथ समाप्त हो सकते हैं जैसे कि आप पूरी क्वेरी को मैन्युअल रूप से करते हैं। तो यह मत समझो कि यह अक्षम होगा क्योंकि डेटाबेस आपको आश्चर्यचकित कर सकता है - उत्पन्न क्वेरी योजना को देखें। एक उल्लेखनीय अपवाद होगा यदि दृश्य में एक ग्रुप बाय क्लॉज़ है जो आउटपुट को प्रभावित करता है - जिस स्थिति में आप 'बाहर' से WHERE नहीं कर सकते।
सिमोन_विवर

8

संग्रहीत कार्यविधियों या कार्यों के बिना इसे करने के लिए एक हैक करने का तरीका यह होगा कि आप अपने डेटाबेस में एक सेटिंग टेबल बनाएं, जिसमें कॉलम Id, Param1, Param2, आदि उस तालिका में एक पंक्ति डालें जिसमें मान Id = 1, Param1 = 0, Parad2 शामिल हैं। = 0, आदि फिर आप वांछित प्रभाव बनाने के लिए अपने दृश्य में उस तालिका में शामिल हो सकते हैं, और दृश्य को चलाने से पहले सेटिंग्स तालिका को अपडेट कर सकते हैं। यदि आपके पास कई उपयोगकर्ता सेटिंग टेबल को अपडेट कर रहे हैं और समवर्ती रूप से दृश्य चला रहे हैं तो चीजें गलत हो सकती हैं, लेकिन अन्यथा यह ठीक काम करना चाहिए। कुछ इस तरह:

CREATE VIEW v_emp 
AS 
SELECT      * 
FROM        emp E
INNER JOIN  settings S
ON          S.Id = 1 AND E.emp_id = S.Param1

देखने के अनुरोध के लिए इसका उपयोग करना भयानक होगा। लेकिन यह इस तरह के छिपे हुए मापदंडों का उपयोग करने के लिए विन्यास / मंच / वातावरण के रूप में वास्तव में प्रयोग करने योग्य है। उसके लिए मेरे लिए एक प्लस।
TPAKTOPA

6

नहीं। यदि आपको एक उपयोगकर्ता परिभाषित फ़ंक्शन का उपयोग करना चाहिए, जिसमें आप मापदंडों को पास कर सकते हैं।


5

नहीं, किसी दृश्य को किसी तालिका से चयन करने के लिए अलग तरीके से नहीं चुना गया है।

आप जो चाहते हैं, वह करने के लिए, एक या अधिक मापदंडों के साथ तालिका-मूल्यवान उपयोगकर्ता-परिभाषित फ़ंक्शन का उपयोग करें


5

एक दृश्य पूर्वनिर्धारित 'चयन' कथन से अधिक कुछ नहीं है। तो केवल वास्तविक उत्तर होगा: नहीं, आप नहीं कर सकते।

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

ऐसा लगता है कि आपको वास्तव में केवल एक क्लॉज़ जोड़ने की आवश्यकता है जब आप अपने दृष्टिकोण से चयन करते हैं, लेकिन आपने वास्तव में सुनिश्चित करने के लिए पर्याप्त विवरण प्रदान नहीं किया है।


5

हम इनपुट मापदंडों के साथ एक संग्रहीत कार्यविधि लिख सकते हैं और फिर दृश्य से सेट परिणाम प्राप्त करने के लिए उस संग्रहीत प्रक्रिया का उपयोग कर सकते हैं। नीचे उदाहरण देखें।

संग्रहीत प्रक्रिया है

CREATE PROCEDURE [dbo].[sp_Report_LoginSuccess] -- [sp_Report_LoginSuccess] '01/01/2010','01/30/2010'
@fromDate datetime,
@toDate datetime,
@RoleName varchar(50),
@Success int
as
If @RoleName != 'All'
Begin
   If @Success!=2
   Begin
   --fetch based on true or false
  Select * from vw_Report_LoginSuccess
  where logindatetime between  dbo.DateFloor(@fromDate) and dbo.DateSieling(@toDate)
  And RTrim(Upper(RoleName)) = RTrim(Upper(@RoleName)) and Success=@Success
   End
   Else
   Begin
    -- fetch all
  Select * from vw_Report_LoginSuccess
  where logindatetime between  dbo.DateFloor(@fromDate) and dbo.DateSieling(@toDate)
  And RTrim(Upper(RoleName)) = RTrim(Upper(@RoleName))
   End

End
Else
Begin
   If @Success!=2
   Begin
  Select * from vw_Report_LoginSuccess
  where logindatetime between  dbo.DateFloor(@fromDate) and dbo.DateSieling(@toDate)
  and Success=@Success
 End
 Else
 Begin
  Select * from vw_Report_LoginSuccess
  where logindatetime between  dbo.DateFloor(@fromDate) and dbo.DateSieling(@toDate)
 End

End

और वह दृश्य जिससे हम परिणाम सेट कर सकते हैं

CREATE VIEW [dbo].[vw_Report_LoginSuccess]
AS
SELECT     '3' AS UserDetailID, dbo.tblLoginStatusDetail.Success, CONVERT(varchar, dbo.tblLoginStatusDetail.LoginDateTime, 101) AS LoginDateTime,
                      CONVERT(varchar, dbo.tblLoginStatusDetail.LogoutDateTime, 101) AS LogoutDateTime, dbo.tblLoginStatusDetail.TokenID,
                      dbo.tblUserDetail.SubscriberID, dbo.aspnet_Roles.RoleId, dbo.aspnet_Roles.RoleName
FROM         dbo.tblLoginStatusDetail INNER JOIN
                      dbo.tblUserDetail ON dbo.tblLoginStatusDetail.UserDetailID = dbo.tblUserDetail.UserDetailID INNER JOIN
                      dbo.aspnet_UsersInRoles ON dbo.tblUserDetail.UserID = dbo.aspnet_UsersInRoles.UserId INNER JOIN
                      dbo.aspnet_Roles ON dbo.aspnet_UsersInRoles.RoleId = dbo.aspnet_Roles.RoleId
WHERE     (dbo.tblLoginStatusDetail.Success = 0)
UNION all
SELECT     dbo.tblLoginStatusDetail.UserDetailID, dbo.tblLoginStatusDetail.Success, CONVERT(varchar, dbo.tblLoginStatusDetail.LoginDateTime, 101)
                      AS LoginDateTime, CONVERT(varchar, dbo.tblLoginStatusDetail.LogoutDateTime, 101) AS LogoutDateTime, dbo.tblLoginStatusDetail.TokenID,
                      dbo.tblUserDetail.SubscriberID, dbo.aspnet_Roles.RoleId, dbo.aspnet_Roles.RoleName
FROM         dbo.tblLoginStatusDetail INNER JOIN
                      dbo.tblUserDetail ON dbo.tblLoginStatusDetail.UserDetailID = dbo.tblUserDetail.UserDetailID INNER JOIN
                      dbo.aspnet_UsersInRoles ON dbo.tblUserDetail.UserID = dbo.aspnet_UsersInRoles.UserId INNER JOIN
                      dbo.aspnet_Roles ON dbo.aspnet_UsersInRoles.RoleId = dbo.aspnet_Roles.RoleId
WHERE     (dbo.tblLoginStatusDetail.Success = 1) AND (dbo.tblUserDetail.SubscriberID LIKE N'P%')  

5

जैसा कि मुझे पता है कि दृश्य कुछ चुनिंदा कमांड की तरह हो सकता है। आप इस चयन के लिए मापदंडों को जोड़ सकते हैं उदाहरण के लिए जहां कथन इस प्रकार हैं:

 WHERE  (exam_id = @var)

4

नहीं, कोई दृश्य स्थिर है। एक चीज जो आप कर सकते हैं (एसक्यूएल सर्वर के संस्करण के आधार पर) एक दृश्य है।

आपके उदाहरण में (केवल एक तालिका को क्वेरी करते हुए), एक अनुक्रमित दृश्य को केवल उस पर एक सूचकांक के साथ तालिका को क्वेरी करने का कोई लाभ नहीं है, लेकिन यदि आप सम्मिलित शर्तों के साथ तालिकाओं पर बहुत सारे जोड़-तोड़ कर रहे हैं, तो एक अनुक्रमित दृश्य प्रदर्शन में काफी सुधार कर सकता है।


4

यदि आप किसी फ़ंक्शन का उपयोग नहीं करना चाहते हैं, तो आप कुछ इस तरह का उपयोग कर सकते हैं

-- VIEW
CREATE VIEW [dbo].[vwPharmacyProducts]
AS
SELECT     PharmacyId, ProductId
FROM         dbo.Stock
WHERE     (TotalQty > 0)

-- Use of view inside a stored procedure
CREATE PROCEDURE [dbo].[usp_GetProductByFilter]
(   @pPharmacyId int ) AS

IF @pPharmacyId = 0 BEGIN SET @pPharmacyId = NULL END

SELECT  P.[ProductId], P.[strDisplayAs] FROM [Product] P
WHERE (P.[bDeleted] = 0)
    AND (P.[ProductId] IN (Select vPP.ProductId From vwPharmacyProducts vPP
                           Where vPP.PharmacyId = @pPharmacyId)
                       OR @pPharmacyId IS NULL
        )

आशा है कि यह मदद करेगा


3

नहीं, आप पैरामीटर को देखने की प्रक्रिया में पास कर सकते हैं


2

यहाँ एक विकल्प है जो मैंने अब तक नहीं देखा है:

केवल वह कॉलम जोड़ें जिसे आप दृश्य में प्रतिबंधित करना चाहते हैं:

create view emp_v as (
select emp_name, emp_id from emp;
)

select emp_v.emp_name from emp_v
where emp_v.emp_id = (id to restrict by)

1

आप बस दृश्य को चलाने के लिए बाईपास कर सकते हैं, एसक्यूएल वाइन और रोएगा लेकिन बस ऐसा करें और इसे चलाएं! आप बचा नहीं सकते।

create or replace view v_emp(eno number) as select * from emp where (emp_id = @Parameter1);

1

आपका दृश्य आपके मापदंडों से युक्त कुछ बाहरी तालिका को संदर्भित कर सकता है।

जैसा कि दूसरों ने उल्लेख किया है, SQL सर्वर में दृश्य में बाहरी इनपुट पैरामीटर नहीं हो सकते हैं। हालाँकि, आप CTE का उपयोग करके अपने दृश्य में एक चर को आसानी से नकली कर सकते हैं। आप इसे SQL सर्वर के अपने संस्करण में परीक्षण-चला सकते हैं।

CREATE VIEW vwImportant_Users AS
WITH params AS (
    SELECT 
    varType='%Admin%', 
    varMinStatus=1)
SELECT status, name 
    FROM sys.sysusers, params
    WHERE status > varMinStatus OR name LIKE varType

SELECT * FROM vwImportant_Users

उपज उत्पादन:

status  name
12      dbo
0       db_accessadmin
0       db_securityadmin
0       db_ddladmin

के माध्यम से भी JOIN

WITH params AS ( SELECT varType='%Admin%', varMinStatus=1)
SELECT status, name 
    FROM sys.sysusers INNER JOIN params ON 1=1
    WHERE status > varMinStatus OR name LIKE varType

के माध्यम से भी CROSS APPLY

WITH params AS ( SELECT varType='%Admin%', varMinStatus=1)
SELECT status, name 
    FROM sys.sysusers CROSS APPLY params
    WHERE status > varMinStatus OR name LIKE varType

1
यह (पीएल / एसक्यूएल और टी-एसक्यूएल कई मायनों में समान हैं), लेकिन यह पता लगाने के लिए एक से अधिक तरीके हैं :) इसे आज़माएं।
ओलेग मेलनिकोव

0

मुझे लगता है कि मैंने अभी तक कोशिश नहीं की है। तुम कर सकते हो:

CREATE VIEW updated_customers AS
SELECT * FROM customer as aa
LEFT JOIN customer_rec as bb
ON aa.id = bb.customer_id
WHERE aa.updated_at between (SELECT start_date FROM config WHERE active = 1) 
and (SELECT end_date FROM config WHERE active = 1)

कॉन्फ़िगरेशन तालिका में आपके पैरामीटर सहेजे और बदले जाएंगे।


2
यदि आपको किसी प्रतिक्रिया की सत्यता के बारे में संदेह है, तो इसे सत्यापित करने से पहले पोस्ट न करें कि यह कम से कम एक पर्याप्त समाधान है। जैसा कि यह खड़ा है, यह एक सवाल के जवाब से अधिक है।
chb

इस समाधान के साथ एक समस्या यह होगी कि यदि क्वेरी को कई सत्रों में चलाया जा रहा है, तो कॉन्फ़िगर तालिका में गलत डेटा का उपयोग किया जा सकता है
User1010

0

मुझे अपनी जरूरतों के लिए इस कार्य का एहसास हुआ

set nocount on;

  declare @ToDate date = dateadd(month,datediff(month,0,getdate())-1,0)

declare @year varchar(4)  = year(@ToDate)
declare @month varchar(2) = month(@ToDate)

declare @sql nvarchar(max)
set @sql = N'
    create or alter view dbo.wTempLogs
    as
    select * from dbo.y2019
    where
        year(LogDate) = ''_year_''
        and 
        month(LogDate) = ''_month_''    '

select @sql = replace(replace(@sql,'_year_',@year),'_month_',@month)

execute sp_executesql @sql

declare @errmsg nvarchar(max)
    set @errMsg = @sql
    raiserror (@errMsg, 0,1) with nowait
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.