0

Given this EXACT ad-hoc query:

DECLARE @list AS TABLE (Name VARCHAR(20))
INSERT INTO @list(Name)
VALUES ('Otter', 'Lebron', 'Aaron', 'Brock')

SELECT *
FROM Users
WHERE FirstName in (SELECT Name from @list)

How can this be done using C# ADO.NET with a SqlParameter?

5
  • 1
    Did you really need to make the table variable for the single value, or is this an over-simplification? In other words, why 2+ statements instead of 1? What would be the parameter? Commented Nov 16, 2011 at 21:11
  • The example was over simplified, edited to make more sense. Commented Nov 16, 2011 at 21:21
  • What kind of parameter would this list be from the ADO.NET side, a DataTable or a string? Commented Nov 16, 2011 at 21:28
  • Well I'm going to have the list represented as a string array... I can convert it to whatever type is necessary, I just don't know what that type should be. I tried both DataTable and List<SqlDataRecord> with no luck. Commented Nov 16, 2011 at 21:34
  • 2
    Pose your question with your constraints UP FRONT. Don't allow people to compose answers for you, waste their time, and throw constraints at them. Very discourteous. Commented Nov 16, 2011 at 21:59

1 Answer 1

4

I'm using a modification of your orginal SQL for sample purposes.

DECLARE @list AS TABLE (Name VARCHAR(20));
INSERT INTO @list(Name)
VALUES ('PROCEDURE'), 
        ('FUNCTION');

SELECT *
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE in (SELECT Name from @list)

You can use a Table-Valued Parameter

Here's a modified example taken from Table-Valued Parameters in SQL Server 2008 (ADO.NET)

        using (SqlConnection cnn = new SqlConnection("Your connection string"))
        {

            var tableParam = new DataTable("names");
            tableParam.Columns.Add("Name", typeof(string));
            tableParam.Rows.Add(new object[] { "PROCEDURE" });
            tableParam.Rows.Add(new object[] { "FUNCTION')" });

            var sql = @"DECLARE @list AS TABLE (Name VARCHAR(20))
                       INSERT INTO @list(Name)
                       SELECT Name from @Names;

                       SELECT *
                       FROM INFORMATION_SCHEMA.ROUTINES
                       WHERE ROUTINE_TYPE in (SELECT Name from @list)";

            var sqlCmd = new SqlCommand(sql, cnn);
            var tvpParam = sqlCmd.Parameters.AddWithValue("@Names", tableParam);
            tvpParam.SqlDbType = SqlDbType.Structured;
            tvpParam.TypeName = "dbo.Names";

            cnn.Open();
            using(SqlDataReader rdr = sqlCmd.ExecuteReader() )
            {
                while (rdr.Read())
                    Console.WriteLine(rdr["SPECIFIC_NAME"]);                    

            }



        }

But you need to define the type dbo.Names before it can work

Here's the type creation SQL

CREATE TYPE dbo.Names AS TABLE 
( Name VARCHAR(Max));

Another option is to use an XML Parameter

 using (SqlConnection cnn = new SqlConnection("Your connection string"))
{



    var sql = @"DECLARE @list AS TABLE (Name VARCHAR(20))
                INSERT INTO @list(Name)
                SELECT t.name.value('.', 'varchar(MAX)')
                FROM   @Names.nodes('/Names/Name') as T(Name);

                SELECT *
                FROM INFORMATION_SCHEMA.ROUTINES
                WHERE ROUTINE_TYPE in (SELECT Name from @list)";

    var sqlCmd = new SqlCommand(sql, cnn);

    var s = new MemoryStream(ASCIIEncoding.Default.GetBytes("<Names><Name>PROCEDURE</Name><Name>FUNCTION</Name></Names>"));


    var xmlParam = new SqlXml(s);

    sqlCmd.Parameters.AddWithValue("@Names", xmlParam);


    cnn.Open();
    using(SqlDataReader rdr = sqlCmd.ExecuteReader() )
    {
        while (rdr.Read())
            Console.WriteLine(rdr["SPECIFIC_NAME"]);                    

    }



}
Sign up to request clarification or add additional context in comments.

2 Comments

I am hoping to achieve this without creating a type because my DBA's are resisting this.
<sigh> Don't know why your DBA would resist that. Its pretty low impact. I guess you other option is XML. updating the answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.