How to specify a parameter as collection in Commandtext - f#

I am using SqlCommandProvider and I need to get some data for each id in an id collection
let ids=["B058A99-C4B2-4CC3-BA9F-034B1F1ECCBD";"A09C01C-D51B-41C1-B44C-0995DD285088"]
[<Literal>]
let qLogo ="""SELECT Id,LogoUrl FROM Hotels WHERE Id IN (#IDS)"""
let queryLogo = new SqlCommandProvider<qLogo,constring>()
queryLogo .Execute(ids)//i need to be able to pass a collection here
`

Long story short, SqlCommandProvider is not even correct type provider to do this (assuming you don't consider string concatenation to build query). The reason is SQL Server only accepts array parameters through calling stored procedure and passing a Table Valued Parameter.
So, to call a stored procedure you need an SqlProgrammabilityProvider to achieve this. But you'll have to create Table Type and Stored Procedure up-front, as described in type provider documentation (scroll down to "Table-valued parameters (TVPs)" section).
Relevant discussion: How to use SQL IN statement in fsharp.data.sqlclient?

Related

How to access document directly through ComsoDB stored procedure

In my stored procedures I often have to access another document, and currently do a query e.g. var query = 'SELECT * from foo f where f.id = "bar"';
I know this will always return 1 result, so is there a way I can access the document directly by id without having to do a query?
You can call a document directly through the REST API with the following URL when using SQL(Core):
https://{databaseaccount}.documents.azure.com/dbs/{db-id}/colls/{coll-id}/docs/{doc-id}
More information about this interface can be found here: Get a Document
Is this what you are looking for?
I know this will always return 1 result, so is there a way I can
access the document directly by id without having to do a query?
Per my knowledge, there is no such method to get document directly without doing a query in stored procedure.
If you want to access the document which is fixed, you could fully pass it into the stored procedure as a json string parameter, without doing a redundant query.
If the accessed document is flexible, you need to query by it's id or it's _self property.

How to pass a parameter to a query using dbExpress in Delphi

I want to use a dbExpress TSQLQuery component. But i do not know how to write the SQL to add a parameter. I will give an example maybe it will be more clear what my problem is.
In a TADOQuery the following works:
SELECT*
FROM sometable
WHERE sometable.id = :value;
Now in the above example you pass the parameter to the query using the colon (:) before the parameter name. But when I try and do that with the TSQLQuery, I get the following error:
dbExpress driver does not support the TDBXTypes.UNKNOWN data type. Vendor Error Message.
Now if this is not the way that you pass a parameter in a TSQLQuery component, can someone please assist me. This is new territory for me.
Im using a Firebird database, and Im using Delphi XE2
To set the properties of a parameter you must use the Params property. From here you can access each paramer using a index or the name, to set the value of the parameter use one of the properties AsString, AsInteger an so on, depeding of the type of the field.
Check this sample
var
LSQLQuery : TSQLQuery;
begin
LSQLQuery:=TSQLQuery.Create(nil);
try
LSQLQuery.SQLConnection:=SQLConnection1;
LSQLQuery.CommandText:='Select FIRST_NAME from EMPLOYEE Where EMP_NO=:Param1';
LSQLQuery.Params.ParamByName('Param1').AsInteger:=2;//or using the index of the parameter LSQLQuery.Params[0].AsInteger:=2;
LSQLQuery.Open;//Execute the query
ShowMessage(LSQLQuery.FieldByName('FIRST_NAME').AsString); //get the data
LSQLQuery.Close;
finally
LSQLQuery.Free;
end;
end;

Can an Oracle stored procedure that has a nested table parameter be called from ODP.NET?

I've got a stored procedure that has a couple parameters that are nested tables.
CREATE TYPE FOO_ARRAY AS TABLE OF NUMBER;
CREATE TYPE BAR_ARRAY AS TABLE OF INTEGER;
CREATE PROCEDURE Blah(
iFoos IN FOO_ARRAY,
iBars IN BAR_ARRAY,
oResults OUT SOMECURSORTYPE
) AS
BEGIN
OPEN oResults FOR
SELECT *
FROM SomeTable T
JOIN TABLE(iFoos) foos ON foos.column_value = T.foo
JOIN TABLE(iBars) bars ON bars.column_value = T.bar;
END
Using ODP.NET (Oracle.DataAccess.dll), is there a way to call this stored procedure and pass arrays into these parameters? The only way I've found to pass arrays is if the parameter type is an associative array (a different type of collection that isn't accessible within SQL).
I made it work this way:
Create a type in the database like "create or replace TYPE NT_LNG IS TABLE OF varchar(2);"
Create a Class implementing IOracleCustomType and INullable (SimpleStringArray)
Create a Class implementing IOracleCustomTypeFactory (SimpleStringArrayFactory). Mark it with this attribute "[OracleCustomTypeMappingAttribute("KNL.NT_LNG")]"
and you pass the parameter like this:
SimpleStringArray sa1 = new SimpleStringArray();
sa1.Array = new String[]{"aaa","bbb"};
OracleParameter param = new OracleParameter("p_lngsrc", OracleDbType.Array, sa1, ParameterDirection.Input);
param.UdtTypeName = "KNL.NT_LNG";
Good Luck
Oracle also offers a free tool to generate a custom .NET class that maps to your nested table type:
Download "Oracle Developer Tools for Visual Studio" (free), open Server Explorer, open "User Defined Types" node, find your user defined type, right click and choose "Generate Custom Class".
Here's a walkthrough to get you started with UDTs in general:
http://www.oracle.com/webfolder/technetwork/tutorials/obe/db/hol08/dotnet/udt/udt_otn.htm

how do i execute a stored procedure with vici coolstorage?

I'm building an app around Vici Coolstorage (asp.net version). I have my classes created and mapped to my database tables and can pull a list of all records fine.
I've written a stored procedure where the query jumps across databases that aren't mapped with Coolstorage, however, the fields in the query result map directly to one of my classes. The procedure takes 1 parameter.
so 2 questions here:
how do i execute the stored procedure? i'm doing this
CSParameterCollection collection = new CSParameterCollection();
collection.Add("#id", id);
var result = Vici.CoolStorage.CSDatabase.RunQuery("procedurename", collection);
and getting the exception "Incorrect syntax near 'procedurename'." (i'm guessing this is because it's trying to execute it as text rather than a procedure?)
and also, since the class representing my table is defined as abstract, how do i specify that result should create a list of MyTable objects instead of generic or dynamic or whatever objects? if i try
Vici.CoolStorage.CSDatabase.RunQuery<MyTable>(...)
the compiler yells at me for it being an abstract class.
There's a shortcut in CoolStorage to run a stored procedure. Simply prefix the stored procedure name with "!":
CSDatabase.RunQuery("!procedurename", collection);

Dynamic Stored Procedure in Sql Server 2005

Is it possible to write a stored procedure with dynamic parameters in sql server 2005
Technically no, but there's a workaround: temp tables. Create a temp table, then set up your stored procedure to read its configuration from the temp table.
Here's an example of how to call it:
CREATE TABLE #inputParams (ParamName VARCHAR(20), ParamValue VARCHAR(20))
INSERT INTO #inputParams (ParamName, ParamValue) VALUES ('First Name', 'John')
INSERT INTO #inputParams (ParamName, ParamValue) VALUES ('Last Name', 'Doe')
EXEC dbo.USP_MyStoredProcedure
and then inside your stored procedure, you could retrieve whatever parameters you needed by checking for the existence of that temp table, and querying the parameters from it like this:
CREATE PROCEDURE dbo.USP_MyStoredProcedure AS
DECLARE #FirstName VARCHAR(20)
SET #FirstName = SELECT ParamValue FROM #inputParams WHERE ParamName = 'First Name'
GO
That way, your stored procedure's number of parameters never changes, which makes it easier for some dev applications to call it over time, but this is reeeeeally dangerous. From the outside of the stored proc, you never have any idea what version of the stored proc you're calling, and whether or not it's going to do anything with the parameters you're sending in.
What you might think about instead is abstracting away your stored proc inside another stored proc as a wrapper.
No, both the count and parameter types are fixed as part of the stored procedure declaration.
If there's a discrete set of parameters you could pass them into the sproc as XML. Then you can shred the XML into variables inside the body of the sproc e.g.
CREATE PROCEDURE MyDynamicStoredProc
#ParameterXML XML
AS
SET NOCOUNT ON
DECLARE #Parameter1 NVARCHAR(50)
DECLARE #Parameter2 INT
SET #Parameter1 = #ParameterXML.value('/Root/Parameters/StringParameter/#Value','nvarchar(50)')
SET #Parameter2 = #ParameterXML.value('/Root/Parameters/IntegerParameter/#Value','int')
...
NB: My XQuery-fu is weak, don't rely on this example!

Resources