Morning all. Got myself a simple query which returns ten rows in SQL Server Management Studio. I call the stored proc by right clicking it and feeding in the parameters.
The results are returned immediately.
In .NET we have set up a dataset class, added a table adapter whose select is this same procedure. I pass in the very same parameters and the execution times out after the standard 30 seconds. It continues to run immediately when called in sql server management studio.
Any ideas why the execution time is seemingly infinite in the .net dataset class.
The query is very simple.
ALTER PROCEDURE [dbo].[usp_GetPostcodeAnalysis]
-- Add the parameters for the stored procedure here
#startDate DATETIME,
#endDate DATETIME,
#customerID INTEGER = NULL,
#siteID INTEGER = -1
AS
DECLARE #itemTypeID INT
SELECT #itemTypeID=ItemTypeID FROM dbo.ItemTypes WHERE ItemTypeName = 'Advert'
DECLARE #SQL NVARCHAR(4000)
BEGIN
SET #SQL = 'SELECT at.ActionTypeName,
COUNT(*) AS "Count"
FROM CustomerSites cs JOIN Items i
ON cs.SiteID = i.SiteID
JOIN Actions a
ON a.ItemID = i.ItemID
JOIN ActionTypes at
ON a.ActionTypeID = at.ActionTypeID
WHERE a.DateAndTime BETWEEN #1 AND #2
AND i.ItemTypeID = #iti
AND at.ActionTypeName IN (''List view'', ''Full view'', ''Email enquiry'', ''Print view'', ''Directions'')'
IF #customerID IS NOT NULL
SET #SQL = #SQL + ' AND i.CustomerID = #c'
IF #siteID > -1
SET #SQL = #SQL + ' AND i.SiteID = #s'
SET #SQL = #SQL + ' GROUP BY
at.ActionTypeName
ORDER BY
at.ActionTypeName'
EXECUTE sp_executesql #SQL,
N'#1 DATETIME, #2 DATETIME, #iti INT, #c INT, #s INT',
#startDate, #endDate, #itemTypeID, #customerID, #siteID
Related
I am running the below PL/SQL block in SQL Developer. I am getting the error Bind Variable "prmMediaDate" is Not Declared. Someone please tell what is missing here:
set serveroutput on;
/* RUN the following as a SCRIPT (F5) */
DECLARE
VARIABLE prmMediaDate varchar2(10);
VARIABLE prmSchdDiv varchar2(2);
VARIABLE prmSchdStore varchar2(4);
VARIABLE prmSchdAssoc varchar2(8);
BEGIN
select '07/17/2017' into :prmMediaDate FROM DUAL;
select '91' into :prmSchdDiv FROM DUAL;
select '91916559' into :prmSchdAssoc FROM DUAL;
SELECT
NVL(ODIV,LA.LABORLEV1NM) AS "schd_division"
,NVL(OLOC,LA.LABORLEV4NM) AS "schd_location"
,NVL(OZONE,LA.LABORLEV5NM) AS "schd_dept"
,NVL(O.ORGPATHTXT,LA.LABORLEV1NM||'-'||LA.LABORLEV4NM||'-'||LA.LABORLEV5NM) AS "orgpath_of_shift"
,SA.SHIFTASSIGNID AS "shiftassignid"
,SA.SHIFTCODEID AS "shiftcodeid"
,SA.ENTEREDONDTM AS "assignmnt_add_dtm"
,ST.ENTEREDONDTM AS "assignmnt_edit_dtm"
,CASE WHEN ST.ACTIONTYPEID IS NULL THEN SA.ENTEREDONDTM ELSE ST.ENTEREDONDTM END as "last_action_dt"
,ST.ACTIONTYPEID AS "last_action_cd"
,AT.SHORTNM AS "last_action_descr"
,SA.DELETEDSW AS "deletedsw"
,TRUNC(SA.SHIFTSTARTDATE) AS "shift_start_date"
,TRUNC(SA.SHIFTENDDATE) AS "shift_end_date"
,TO_CHAR(SA.SHIFTSTARTDATE, 'HH24:MI:SS') AS "shift_start_time"
,TO_CHAR(SA.SHIFTENDDATE, 'HH24:MI:SS') AS "shift_end_time"
,CASE SA.SHIFTTYPEID WHEN 1 THEN 'WORK SHIFT' WHEN 2 THEN 'UNAVAIL' WHEN 3 THEN 'HIDE SHFT' WHEN 4 THEN 'SCHD PAYCD EDIT' WHEN 5 THEN 'HIDE WRK SHFT' WHEN 6 THEN 'HIDE UNAVAIL DAY' ELSE 'UNDEFINED' END as "segment"
,NVL(LA.LABORLEV2DSC,'9999') AS "sell_nonsell"
,P.PERSONNUM AS "assoc_nbr"
,SA.ENTEREDONDTM AS "entered_on_dtm"
from PERSON P
JOIN SHIFTASSIGNMNT SA on SA.EMPLOYEEID = P.PERSONID
JOIN COMBHOMEACCT HA on (P.PERSONID = HA.EMPLOYEEID)
LEFT JOIN SHFTSEGORGTRAN SSOT on SSOT.SHIFTASSIGNID = SA.SHIFTASSIGNID
LEFT JOIN ORGX O on O.ORGIDSID = SSOT.ORGIDSID
LEFT JOIN SHFTASGNMNTTRC ST on ST.SHIFTASSIGNID = SA.SHIFTASSIGNID
LEFT JOIN ACTIONTYPE AT on AT.ACTIONTYPEID = ST.ACTIONTYPEID
LEFT JOIN LABORACCT LA on (LA.LABORACCTID = HA.LABORACCTID)
WHERE
TRUNC(SA.SHIFTSTARTDATE) = :prmMediaDate
AND :prmMediaDate BETWEEN HA.EFFECTIVEDTM AND (HA.EXPIRATIONDTM - 1)
AND ((:prmMediaDate BETWEEN O.EFFECTIVEDTM AND (O.EXPIRATIONDTM - 1)) OR (O.EFFECTIVEDTM IS NULL))
AND (SSOT.SEGMENTNUM = 1 OR SSOT.SEGMENTNUM IS NULL)
AND (TRUNC(SSOT.SHIFTSTARTDATE) = :prmMediaDate OR SSOT.SHIFTSTARTDATE IS NULL)
AND SA.DELETEDSW = 0
AND (O.ODIV = :prmSchdDiv OR LA.LABORLEV1NM = :prmSchdDiv)
AND P.PERSONNUM = :prmSchdAssoc;
end;
/
I have tried multiple options like declaring VARIABLE as var, set Scan ON etc.. But it didnt help.
You need to understand that declare is pl/sql and variable is part of sql*plus program commands.
So to successfully execute that code you need to remove DECLARE command.
Set Serveroutput On;
/* RUN the following as a SCRIPT (F5) */
--DECLARE
Variable Prmmediadate Varchar2(10);
Begin
Select '07/17/2017' Into :Prmmediadate From Dual;
End;
/
print :Prmmediadate
PL/SQL procedure successfully completed.
PRMMEDIADATE
--------------------------------------------------------------------------------
07/17/2017
There is a stored procedure which contains many insert, update, delete and truncate statements. I want to group all the statements one by one into a table.
For example:
create proc Get_Tables as
begin
UPDATE BB_FMCTransactionsTwo SET wsTradeDate = wsSettleDate WHERE wsEntryCode = 'NRT'
UPDATE BB_FMCTransactionsTwo SET wsOK = 1, wsSpecialLogic = SpecialLogic FROM BB_EntryCode INNER JOIN BB_FmcTransactionsTwo ON EntryCode = wsEntryCode
UPDATE BB_FMCTransactionsTwo SET wsFMCFtNt = '' FROM BB_EntryCode INNER JOIN BB_FmcTransactionsTwo ON EntryCode = wsEntryCode WHERE wsBS <> 'B' AND ( FMCFtNtB IS NULL OR FMCFtNtB = 'PR' )
UPDATE BB_B204_Tran SET AMOUNT = dbo.BCA_AMT(Desc1, Desc2, Desc3, Udesc1, Udesc2, Udesc3) WHERE TRANIND = 14 AND PORTTYPE IN (2,3)
DELETE BB_B204_Tran WHERE TRANIND = 14 AND PORTTYPE IN(2,3) AND (Quantity IS NULL OR ISNUMERIC(Quantity) = 0 OR Quantity = -1 OR ISNUMERIC(AMOUNT) = 0
end
Required:
I want to insert the update statements, delete statements into a table one by one...
Create a stored procedure which divides the stored procedure based on type of statements (Insert, Update, Truncate) and inserts that into a table row by row. So that the table looks like below.
Table:
Sl.No Statement
1 UPDATE BB_FMCTransactionsTwo SET wsTradeDate = wsSettleDate WHERE wsEntryCode = 'NRT'
2 DELETE BB_B204_Tran WHERE TRANIND = 14 AND PORTTYPE IN(2,3)
I have implemented for your first update statement and assume that your AuditTable will have one column SQLData and so you need to store these SQL Statements in your store procedure and if you have used any variable then you need to store into SQL Data variable and insert into Audit Table. it may help you.
declare ##SQL1 varchar(max)
UPDATE BB_FMCTransactionsTwo SET wsTradeDate = wsSettleDate WHERE wsEntryCode = 'NRT'
set ##SQL1 = 'UPDATE BB_FMCTransactionsTwo SET wsTradeDate = wsSettleDate WHERE wsEntryCode = ''NRT'''
insert into AuditTable (SQLData) values(##SQL1)
For Variable:
DECLARE ##wsEntryCode VARCHAR(100)
SET ##wsEntryCode='NRT'
PRINT 'UPDATE BB_FMCTransactionsTwo SET wsTradeDate = wsSettleDate WHERE wsEntryCode = ''' + ##wsEntryCode + ''''
insert into AuditTable (SQLData) values(##SQL1)
I've got an ASP.net search page where the user can enter one or more search criteria. The page calls a stored procedure to query a MS SQL Server 2008 db.
Part of the search criteria is single date or date range. If the user supplies Date1, we search on a single date. If the user supplies Date1 and Date2, we search on a date range.
My issue is coding this logic in the stored proc.
#Date1 datetime
#Date2 datetime
..other search params...
So there are three conditions:
Both #Date1 and #Date2 are null (the user is not searching on dates)
#Date1 is not null and #Date2 is null (the user is searching on a single date)
#Date1 is not null and #Date2 is not null (user is searching a date range)
I can't figure out how to structure the WHERE clause to handle each of the three possible conditions.
I'm familiar with ISNULL() and COALESCE()
Any tips or suggestions are greatly appreciated.
CREATE PROCEDURE BLABLABLA(
#DATE1 DATETIME = NULL,
#DATE2 DATETIME = NULL
)
AS
BEGIN
SELECT COL1, COL2
FROM THE_TABLE
WHERE
THE_TABLE.DATETIMEFIELD BETWEEN
ISNULL(#DATE1, THE_TABLE.DATETIMEFIELD)
AND COALESCE(#DATE2, #DATE1, THE_TABLE.DATETIMEFIELD)
END
Another choice, losing some expressiveness but likely using indexes, could be:
CREATE PROCEDURE BLABLABLA(
#DATE1 DATETIME = NULL,
#DATE2 DATETIME = NULL
)
AS
BEGIN
SELECT COL1, COL2
FROM THE_TABLE
WHERE
(THE_TABLE.DATETIMEFIELD >= #DATE1 OR #DATE1 IS NULL)
AND (THE_TABLE.DATETIMEFIELD <= #DATE2
OR THE_TABLE.DATETIMEFIELD = #DATE1
OR (#DATE1 IS NULL AND #DATE2 IS NULL))
END
You could try to create your SQL query as a string in the SP and then execute it, like this:
...
declare #sql varchar(500)
set #sql = 'select from myTable where 1=1'
if(#Date1 <> null)
set #sql = #sql + ' and date1 >= '+ #date1
if(#Date2 <> null)
set #sql = #sql + ' and date2 <= '+ #date2
print(#sql) -- for debug
exec(#sql)
I have a name/value pair in a List<T> and needing to find the best way to pass these to a stored procedure.
Id Name
1 abc
2 bbc
3 cnn
....
...
What is the best way to accomplish this?
One way to handle this in SQL Server 2005 (prior to the availability of table valued parameters) was to pass a delimited list and use a Split function. If you are using a two-column array, you would want to use two different delimiters:
Declare #Values varchar(max)
Set #Values = '1,abc|2,bbc|3,cnn'
With SplitItems As
(
Select S.Value As [Key]
, S2.Value
, Row_Number() Over ( Partition By S.Position Order By S2.Position ) As ElementNum
From dbo.Split(#Values,'|') As S
Outer Apply dbo.Split(S.Value, ',') As S2
)
Select [Key]
, Min( Case When S.ElementNum = 1 Then S.Value End ) As ListKey
, Min( Case When S.ElementNum = 2 Then S.Value End ) As ListValue
From SplitItems As S
Group By [Key]
Create Function [dbo].[Split]
(
#DelimitedList nvarchar(max)
, #Delimiter nvarchar(2) = ','
)
RETURNS TABLE
AS
RETURN
(
With CorrectedList As
(
Select Case When Left(#DelimitedList, Len(#Delimiter)) <> #Delimiter Then #Delimiter Else '' End
+ #DelimitedList
+ Case When Right(#DelimitedList, Len(#Delimiter)) <> #Delimiter Then #Delimiter Else '' End
As List
, Len(#Delimiter) As DelimiterLen
)
, Numbers As
(
Select Row_Number() Over ( Order By c1.object_id ) As Value
From sys.columns As c1
Cross Join sys.columns As c2
)
Select CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
, Substring (
CL.List
, CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen
, CharIndex(#Delimiter, CL.list, N.Value + 1)
- ( CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen )
) As Value
From CorrectedList As CL
Cross Join Numbers As N
Where N.Value < Len(CL.List)
And Substring(CL.List, N.Value, CL.DelimiterLen) = #Delimiter
)
Another way to handle this without table-valued parameters is to pass Xml as an nvarchar(max):
Declare #Values nvarchar(max)
Set #Values = '<root><Item Key="1" Value="abc"/>
<Item Key="2" Value="bbc"/>
<Item Key="3" Value="cnn"/></root>'
Declare #docHandle int
exec sp_xml_preparedocument #docHandle output, #Values
Select *
From OpenXml(#docHandle, N'/root/Item', 1)
With( [Key] int, Value varchar(10) )
Take a look at Arrays and Lists in SQL Server 2008 to get some ideas
SQL Server 2008 also supports this multi row values syntax
create table #bla (id int, somename varchar(50))
insert #bla values(1,'test1'),(2,'Test2')
select * from #bla
i endup using foreach <insert>
This could done through three ways.
User Defined Table Type
Json Object Parsing
XML Parsing
I tried with the first option and passed a list of pairs in User Defined Table Type. This works for me. I am posting here, it might help someone else.
The first challenge for me was to pass the list of key value pair data structure and second to loop through the list and insert the record in a table.
Step 1 : Create a User Defined Table Type. I have created with a name 'TypeMetadata'. As it is custom type, I created two attributes of type nvarchar. You can create one of type integer and second of type nvarchar.
-- Type: metadata ---
IF EXISTS(SELECT * FROM SYS.TYPES WHERE NAME = 'TypeMetadata')
DROP TYPE TypeMetadata
GO
CREATE TYPE TypeMetadata AS TABLE (
mkey nvarchar (50),
mvalue nvarchar (50)
);
GO
Step 2 : Then I created a stored procedure with name 'createfiled'
-- Procedure: createtext --
CREATE PROCEDURE [dbo].[createfield]
#name nvarchar(50),
#text nvarchar(50),
#order int,
#type nvarchar(50),
#column_id int ,
#tid int,
#metadataList TypeMetadata readonly
AS
BEGIN
--loop through metadata and insert records --
DECLARE #mkey nvarchar(max);
DECLARE #mvalue nvarchar(max);
DECLARE mCursor CURSOR LOCAL FAST_FORWARD
FOR
SELECT mkey, mvalue
FROM #metadataList;
OPEN mCursor;
FETCH NEXT FROM mCursor INTO #mkey, #mvalue; -- Initial fetch attempt
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO template_field_metadata (name, value, template_field_id, isProperty) values (#mkey, #mvalue, 1, 0)
PRINT 'A new metadata created with id : ' + cast(SCOPE_IDENTITY() as nvarchar);
FETCH NEXT FROM mCursor INTO #mkey, #mvalue; -- Attempt to fetch next row from cursor
END;
CLOSE mCursor;
DEALLOCATE mCursor;
END
GO
Step 3: finally I executed the stored procedure like;
DECLARE #metadataToInsert TypeMetadata;
INSERT INTO #metadataToInsert VALUES ('value', 'callVariable2');
INSERT INTO #metadataToInsert VALUES ('maxlength', '30');
DECLARE #fid INT;
EXEC [dbo].[createfield] #name = 'prefagent', #text = 'Pref Agent', #order = 1 , #type= 'prefagent', #column_id = 0, #tid = 49, #metadataList =#metadataToInsert;
i wonder if i could run the following procedure in SQLite:
set nocount on
select T.ID, max(T.SerialNo) as SerialNo
into #Tmp_Ticket_ID
from Ticket as T, Ticket as inserted
where t.ID = inserted.ID
group by T.id having count(*) > 1
declare zeiger cursor for
select SerialNo
from #Tmp_Ticket_ID
declare #SerialNo int
OPEN Zeiger
FETCH NEXT FROM zeiger INTO #SerialNo
WHILE (##fetch_status <> -1)
BEGIN
IF (##fetch_status <> -2)
BEGIN
update T
set ID = (select max(id) + 1 from Ticket)
from ticket AS T, #Tmp_Ticket_ID as I
where t.serialNo = i.serialno
and I.Serialno = #SerialNo
END
FETCH NEXT FROM zeiger INTO #SerialNo
END
CLOSE Zeiger
DEALLOCATE Zeiger
DROP TABLE #Tmp_Ticket_ID
This is a little procedure from a ms-sql2000 which cleans doubles of Ticket_id's in a given table Ticket of the following structur:
create table Ticket (serialNo int identity(1,1) not null
, ID as int not null
, Ticket_issue as varchar(50)
, some_more_field varchar(500))
Due to a simple merger from different databases, the ticket_id's becomes not unique. To fix by renumbering this i developed this procedure but now we have a similar issue on a SQLite-db.
delete from Ticket
where exists
(select rowid from Ticket t2
where t2.ID = Ticket.ID and t2.rowid < Ticket.rowid)
rowid is the always-present SQLite btree index column.
Thanks to Martin Engelschalk on the SQLite mailing list on 2009-08-17.