declare variable $mRec := "010155-00";
for $pi in /NTSFP10/dbo_PatRefInfo/ROW
for $pa in /NTSFP10/dbo_Patient/ROW
where $pi/PatientID = $pa/PATID and $pa/PATID = $mRec
return ($pa/PATID)
Nothing is returned, but I have verified the mRec exists in each table. both are nvarchar or varchar
Sample data file
Related
I'm very new to tSQLt and am having some difficulty with what should really be a very simple test.
I have added a column to the SELECT statement executed within a stored procedure.
How do I test in a tSQLt test that the column is included in the resultset from that stored procedure?
Generally, when adding a column to the output of a stored procedure, you will want to test that the column both exists and is populated with the correct data. Since we're going to make sure that the column is populated with the same data, we can design a test that does exactly that:
CREATE PROCEDURE MyTests.[test stored procedure values MyNewColumn correctly]
AS
BEGIN
-- Create Actual and Expected table to hold the actual results of MyProcedure
-- and the results that I expect
CREATE TABLE MyTests.Actual (FirstColumn INT, MyNewColumn INT);
CREATE TABLE MyTests.Expected (FirstColumn INT, MyNewColumn INT);
-- Capture the results of MyProcedure into the Actual table
INSERT INTO MyTests.Actual
EXEC MySchema.MyProcedure;
-- Create the expected output
INSERT INTO MyTests.Expected (FirstColumn, MyNewColumn)
VALUES (7, 12);
INSERT INTO MyTests.Expected (FirstColumn, MyNewColumn)
VALUES (25, 99);
-- Check that Expected and Actual tables contain the same results
EXEC tSQLt.AssertEqualsTable 'MyTests.Expected', 'MyTests.Actual';
END;
Generally, the stored procedure you are testing relies on other tables or other stored procedures. Therefore, you should become familiar with FakeTable and SpyProcedure as well: http://tsqlt.org/user-guide/isolating-dependencies/
Another option if you are just interested in the structure of the output and not the content (and you are running on SQL2012 or greater) would be to make use of sys.dm_exec_describe_first_result_set_for_object in your test.
This dmo (dynamic management object) returns a variety of information about the first result set returned for a given object.
In my example below, I have only used a few of the columns returned by this dmo but others are available if, for example, your output includes decimal data types.
In this test, I populate a temporary table (#expected) with information about how I expect each column to be returned - such as name, datatype and nullability.
I then select the equivalent columns from the dmo into another temporary table (#actual).
Finally I use tSQLt.AssertEqualsTable to compare the contents of the two tables.
Having said all that, whilst I frequently write tests to validate the structure of views or tables (using tSQLt.AssertResultSetsHaveSameMetaData), I have never found the need to just test the result set contract for procedures. Dennis is correct, you would typically be interested in asserting that the various columns in your result set are populated with the correct values and by the time you've covered that functionality you should have covered every column anyway.
if object_id('dbo.myTable') is not null drop table dbo.myTable;
go
if object_id('dbo.myTable') is null
begin
create table dbo.myTable
(
Id int not null primary key
, ColumnA varchar(32) not null
, ColumnB varchar(64) null
)
end
go
if object_id('dbo.myProcedure') is not null drop procedure dbo.myProcedure;
go
create procedure dbo.myProcedure
as
begin
select Id, ColumnA, ColumnB from dbo.myTable;
end
go
exec tSQLt.NewTestClass #ClassName = 'myTests';
if object_id('[myTests].[test result set on SQL2012+]') is not null drop procedure [myTests].[test result set on SQL2012+];
go
create procedure [myTests].[test result set on SQL2012+]
as
begin
; with expectedCte (name, column_ordinal, system_type_name, is_nullable)
as
(
-- The first row sets up the data types for the #expected but is excluded from the expected results
select cast('' as nvarchar(200)), cast(0 as int), cast('' as nvarchar(200)), cast(0 as bit)
-- This is the result we are expecting to see
union all select 'Id', 1, 'int', 0
union all select 'ColumnA', 2, 'varchar(32)', 0
union all select 'ColumnB', 3, 'varchar(64)', 1
)
select * into #expected from expectedCte where column_ordinal > 0;
--! Act
select
name
, column_ordinal
, system_type_name
, is_nullable
into
#actual
from
sys.dm_exec_describe_first_result_set_for_object(object_id('dbo.myProcedure'), 0);
--! Assert
exec tSQLt.AssertEqualsTable '#expected', '#actual';
end
go
exec tSQLt.Run '[myTests].[test result set on SQL2012+]'
In my project EF calls a stored procedure which is shown below. It returns either 1 or scope identity.
On EF function imports, the stored procedure is listed with a return type of decimal.
When the stored procedure returns scope identity, everything is ok.
But when if condition of sp satisfies, ef throws error as
The data reader returned by the store data provider does not have enough columns for the query requested.
Pls help..
This is my stored procedure:
#VendorId int,
#ueeareaCode varchar(3),
#TuPrfxNo varchar(3),
#jeeSfxNo varchar(4),
#Tjode varchar(3),
#uxNo varchar(3),
#TyufxNo varchar(4),
#Iyuy bit
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
SET NOCOUNT ON;
IF EXISTS (Select dfen_id
from dbo.efe_phfedwn_eflwn
where
[yu] = #Tyuode and
[uy] = #TuyxNo and
[yuno] = #Tuo)
return 1
ELSE
Begin
INSERT INTO dbo.yu
....................
Select Scope_Identity()
End
END
The error tells us that EF is expecting a result set and when we use RETURN we don't get a result set. Your error means that the stored procedure is returning an integer but EF is expecting a decimal, so we just CAST the selected values to a decimal.
So modify the SQL so that we SELECT instead of RETURN, like so (not forgetting to use CAST):
IF EXISTS (Select cntct_ctr_phn_ln_id
from dbo.cntct_ctr_phn_ln
where
[toll_free_phn_area_cd] = #TollfreeareaCode and
[toll_free_phn_prfx_no] = #TollfreePrfxNo and
[toll_free_phn_sfx_no] = #TollfreeSfxNo)
SELECT CAST(1 AS decimal)
Then also CAST the result of SCOPE_IDENTITY() to a decimal:
SELECT CAST(SCOPE_IDENTITY() AS decimal)
I have an aspx page with the following controls: TextBox, CheckBoxList, DropDownList.
They are used to specify search criteria. The records are taken from SQL Server Data Base using a stored procedure.
Each CheckBox in CheckBoxList has a value which is actual ID of a Product Group in the database. If more than one checkbox is selected, how to pass the list of IDs to a stored procedure as a set so I could use IN #IdList? What variable types should I use in C# and T-SQL? Is it possible at all?
DropDownList's first item is "ALL". When "ALL" is selected, I need to pass something like NULL to the stored procedure. How to make the stored procedure to ignore a parameter if it is NULL?
CREATE PROCEDURE FilterList
#ProductName nvarchar(200),
#ProductGroupID int
AS BEGIN
SELECT
prod_id AS 'ID',
prod_name AS 'Name'
FROM
dbo.Products
WHERE
prod_group_id = #ProductGroupID OR
prod_name = #ProductName
END
You can achieve optional parameters in T-SQL stored procedures by having default values equal NULL.
Example where NULL is used as "ignore this parameter":
CREATE PROCEDURE [dbo].[dcspFilterEmpList]
#ProductName nvarchar(200) = null,
#ProductGroupID int = null
AS BEGIN
SELECT
prod_id AS 'ID',
prod_name AS 'Name'
FROM dbo.Products
WHERE (prod_group_id = #ProductGroupID OR #ProductGroupID IS NULL)
AND (prod_name = #ProductName OR #ProductName IS NULL)
END
It's perfectly fine to define a stored procedure to take a table-valued parameter in T-SQL.
Here is an article on the subject http://sqlwithmanoj.wordpress.com/2012/09/10/passing-multipledynamic-values-to-stored-procedures-functions-part4-by-using-tvp/
If you need more info on this google for "table-valued parameter"
Example using multi-valued parameters:
CREATE TYPE XTV_ProductNames AS TABLE --extension, table valued == XTV
( ProductName nvarchar(50))
GO
CREATE TYPE XTV_ProductGroups AS TABLE --extension, table valued == XTV
( ProductGroupID int))
GO
CREATE PROCEDURE [dbo].[dcspFilterEmpList]
#TVP1 XTV_ProductNames READONLY
,#TVP2 XTV_ProductGroups READONLY
AS BEGIN
SELECT
prod_id AS 'ID',
prod_name AS 'Name'
FROM dbo.Products as p
INNER JOIN #TVP1 as s
ON p.prod_name = s.ProductName
UNION
SELECT
prod_id AS 'ID',
prod_name AS 'Name'
FROM dbo.Products as p
INNER JOIN #TVP2 as s
ON p.prod_group_id = s.ProductGroupID
END
Your answer was correct David, but it was a little misleading because the parameter equaling NULL does not make it optional; it just has to be set to any value period. This also creates optional parameters:
CREATE PROCEDURE [dbo].[dcspFilterEmpList]
#ProductName nvarchar(200) = 'DefaultProduct',
#ProductGroupID int = 1
AS
Which could thus be executed without passing any parameters, i.e.:
EXEC [dbo].[dcspFilterEmpList]
I understand that this wasn't necessarily what Piscovetz was trying to do, but it seems to match more closely the actual topic question shown, and it is an important distinction.
ALTER PROCEDURE [dbo].[Signin_Check]
#uid varchar(50), #pwd varchar(50), #uname varchar(50) output
AS
IF EXISTS (SELECT * FROM threeLayer_user WHERE uid = #uid and pass = #pwd)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT #uname = name
FROM threeLayer_user
WHERE uid = #uid and pass = #pwd
RETURN #uname
END
This stored procedure is throwing an error :
Conversion failed when converting the varchar value 'Saurav' to data type int.
Your code contains the line
return #uname
the return statement can only accept integer values. However, your #uname parameter is an output parameter, so you do not need to also return it. Just make sure that you specify OUTPUT when calling the sproc:
EXEC dbo.Signin_Check #uid, #password, #uname OUTPUT;
The SP doesn't seem to have bad code related to the error, could you check well the parameters being passed to the stored procedure (i.e. their order and their type)? The problem can be the values that you are passing and not the actual procedure.
Could you append to your post the code you are using when you invoke the stored procedure?
Are you sure that it's varchar column?
#uid varchar(50) / int
uid = #uid
I have a stored procedure that I return the new ID number. The code looks like this:
ALTER PROCEDURE [dbo]. [Save Contact]
#FirstName varchar (50),
#LastName varchar (50),
#Email varchar (50)
AS
BEGIN
- SET NOCOUNT ON added to Prevent extra result sets from
- Interfering with SELECT statements.
SET NOCOUNT ON;
INSERT INTO Contacts (FirstName, LastName, Email)
VALUES (#FirstName, #LastName, #Email)
SELECT SCOPE_IDENTITY() as newid
END
When I try to map my stored procedures I get the following error:
Error 1 Error 2047: A mapping function binding specifier a function demoModel.Store.SaveContact with an unsupported parameter: id. Output parameters May only be mapped through the RowsAffectedParameter property. Use result bindings to return values from a function invocation.
Is there anyone here who can see what I'm doing wrong?
Need more code, let me know.
With the SQL as it is above remove id as a parameter for the insert statement. Its not needed. To get SCOPE_IDENTITY() you only need to map newid it in the Result Column Bindings.
Also ensure that the column name in Result Column Bindings is the same case as the stored procedure is returning.
Source: http://blogs.msdn.com/b/adonet/archive/2008/03/26/stored-procedure-mapping.aspx