Retrieving metadata (table name) from a SQL statement - c#

I am using Visual Studio 2008.
I have created a Winforms application, and I am trying to extract the table name from a SQL statement.
con = new SqlConnection(connString);
String queryString = "Select CUSTOMER_NAME from CUSTOMER_DETAIL";
Is there any function to do so?
Please help me out.

It's good that you have mentioned Java's ResultSetMetaData. Quoting that link:
public interface ResultSetMetaData
An object that can be used to get information about the types and
properties of the columns in a ResultSet object.
As for C#, you can get the same information using the DataColumn Class.
DataType Property of DataColumn class can be used to get (and to set) the type of data stored in column, AllowDBNull can be used to get (and set) the value that indicates whether null values are allowed in this column, etc... To get the full list of DataColumn properties follow the link I have posted above.
Sample code (gets column datatype):
SqlConnection con = new SqlConnection(connString);
String queryString = "Select CUSTOMER_NAME from CUSTOMER_DETAIL";
SqlCommand cmd = new SqlCommand(queryString, con);
DataTable myTable = new DataTable();
myTable.Load(cmd.ExecuteReader());
DataColumn column = myTable.Columns[0]; // zero based index of column, alternatively use column name
string typeOfColumn = column.DataType.Name; // or column.DataType.FullName to get the fully qualified name of the System.Type

I found this site that has a GREAT parser....
http://www.sqlparser.com/
well worth it. Works a treat......

Try using "Interop - SQLDMO"
Else you might have to write your own custom class
Rather than using a function that evaluates a string (in which the query is written), I'd suggest you make a custom SQL query builder class (as per your requirements) and then write your methods or extensions to achieve your goal of getting metadata of the query
That is if you have no option but to use SQL-queries directly in your c# code
Hope this helps.

This is the Method which gives us tablename just change the SQL query string,connection String
Works with simple query,Joins too
public static List<string> getTablenames(string connString,string QueryString)
{
SqlConnection con = new SqlConnection(connString);
con.Open();
DataTable dt = con.GetSchema("Tables");
List<string> getTableName = new List<string>();
List<string> tablenames = new List<string>();
foreach (DataRow dr in dt.Rows)
{
tablenames.Add(dr[2].ToString());
}
for (int ii = 0; ii < dt.Rows.Count; ii++)
{
string myTable = tablenames[ii];
Boolean checkMyTable = QueryString.Contains(myTable);
if (checkMyTable == true)
{
getTableName.Add(myTable);
}
}
con.Close();
return getTableName;
}
thanxx StackoverFlow

Related

How can I retrieve the query definition (SQL text) of an Access query and store back a changed definition

I have a requirement where I need to read queries from Access DB in c# and check if the access db query has any keyword like "KEY" if it has keywords I need to enclose that in square brackets"[]".just like how it is done in SQL.
Could someone suggest me how to do that?
You can retrieve the query text like this:
string connString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\...\myDB.mdb";
using (var conn = new OleDbConnection(connString )) {
conn.Open();
string[] restrictions = new string[] { null, null, "myQuery" };
DataTable schema = conn.GetSchema("Views", restrictions);
if (schema.Rows.Count > 0) {
DataRow row = schema.Rows[0];
string queryText = (string)row["VIEW_DEFINITION"];
Console.WriteLine(queryText);
}
}
If you drop the restrictions argument with the query name, conn.GetSchema("Views") returns one row for each query. If you query conn.GetSchema("Procedures") other types of queries like insert, update and DDL statements that are not considered as queries are returned in row["PROCEDURE_DEFINITION"].
View (query) names are returned in row["TABLE_NAME"] and procedure names in row["PROCEDURE_NAME"].
And you can update the query like this:
using (var conn = new OleDbConnection(connString)) {
conn.Open();
var cmd = new OleDbCommand("DROP PROCEDURE myQuery", conn);
cmd.ExecuteNonQuery();
cmd = new OleDbCommand("CREATE PROCEDURE myQuery AS SELECT * FROM myTable", conn);
cmd.ExecuteNonQuery();
}
Strangely enough the OleDb CREATE DDL (Data Definition Language) designates the queries as 'procedures' but the schema table returns a 'VIEW_DEFINITION' and the query name is returned in the column 'TABLE_NAME'. SELECT queries must be retrieved as "Views", other types of queries as "Procedures"; however, both types are created as PROCEDUREs.
While I was testing the answer that #Olivier Jacot-Descombes provided, I was not able to retreive all the queries text representation. Therefore I applied some other method where you open the existing Ms Access database instance and read the queries that are stored in it.
Here is the class I used:
public class MsAccess
{
private Microsoft.Office.Interop.Access._Application _oAccess;
public MsAccess(string path)
{
_oAccess = (Microsoft.Office.Interop.Access._Application)System.Runtime.InteropServices.Marshal.BindToMoniker(path);
}
public string ReturnSqlQueryText(string queryName)
{
string queryDef = null;
var qdefs = _oAccess.CurrentDb().QueryDefs;
foreach (QueryDef qdef in qdefs)
{
if(qdef.Name.Equals(queryName))
queryDef = qdef.SQL;
}
return queryDef;
}
}
Using this code might require you adding using Microsoft.Office.Interop.Access.Dao and Microsoft.Office.Interop.Access both (15.0.0.0) where you can find them under Extension on the reference menu

Should I use datatable to store one column of select query in asp.net

My sql select query will return one column of company names (many rows of names). Now I want to store it. I used:
try
{
connection.Open();
sqlCmd = new SqlCommand(sqlCmd.CommandText, connection);
SqlDataReader sqlReader = sqlCmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Clear();
sqlReader.Read();
dt.Load(sqlReader);
Then I tried to access the name by
dt.Rows[0][0].ToString()
dt.Rows[1][0].ToString()
dt.Rows[2][0].ToString()
etc.
But I recognize that the value in dt.Rows[0][0].ToString() is different from time to time, event if I use the same query, and it looks like that the old values still stored in the datatable event if I use new query value.
How is the right way to store and retrieve values here?
You can use,
string compnay_name = dt.Rows[0]["column_name"].ToString();
Try using your compnay name column in double quote.
You can use it in a for or foreach loop.
as,
for(int i=0;i<count;i++)
{
string compnay_name = dt.Rows[i]["column_name"].ToString();
}
Hope it helps...
Aki

How can I get a list of the columns in a SQL SELECT statement?

I'm wanting to get a list of the column names returned from a SQL SELECT statement. Can someone suggest an easy way to do this?
I have a tool that lets users define a query using any SQL SELECT statement. The results of the query are then presented in a custom manner. To set up the presentation, I need to know the column names so that the user can store formatting settings about each column.
Btw, the formatting settings are all being created via ASP.NET web pages, so the query results will end up in .NET if that helps with any ideas people have.
Any ideas?
You should be able to do this using the GetName method. Something like this probably:
SqlDataReader mySDR = cmd.ExecuteReader();
for(int i = 0;i < mySDR.FieldCount; i++)
{
Console.WriteLine(mySDR.GetName(i));
}
This is something you could do entirely from a asp.net page. No special/extra SQL required.
Assuming SQL Server: You could use SET FMTONLY to just return metadata (and not the actual data), e.g.:
USE AdventureWorks2008R2;
GO
SET FMTONLY ON;
GO
SELECT *
FROM HumanResources.Employee;
GO
SET FMTONLY OFF;
GO
You can get by something as following
Note : You need to fill the DataTable of the Dataset.........
DataSet1 DataSet1 = new DataSet1();
DataTable dt = DataSet1.Tables(0);
DataColumn dc = null;
foreach (DataColumn dc_loopVariable in dt.Columns) {
dc = dc_loopVariable;
Response.write(dc.ColumnName.ToString() + " " + dc.DataType.ToString() + "<br>");
}
Another method to just return meta data is
select top 0 * from table
If you know the table name you could try using:
desc <table_name>
I'm assuming you are using SQL Server.
Or as an alternative:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TableNameGoesHere'
ORDER BY ORDINAL_POSITION
You might want to use the second option if you are going to be using ASP.NET
This will get you more than the column name if you need more information about each column like size, ordinal,etc. A few of the most important properties are listed, but there are more.
Note, DataObjects.Column is a POCO for storing column information. You can roll your own in your code. Also, note I derive the .Net type as well, useful for converting SQL data types to .Net (C#) ones. ConnectionString and TableName would be supplied from a caller.
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
conn.Open();
SqlCommand comm = new SqlCommand("Select top(1) * from " + TableName + " Where 1=0");
comm.CommandType = CommandType.Text;
comm.Connection = conn;
using (SqlDataReader reader = comm.ExecuteReader(CommandBehavior.KeyInfo))
{
DataTable dt = reader.GetSchemaTable();
foreach (DataRow row in dt.Rows)
{
//Create a column
DataObjects.Column column = new DataObjects.Column();
column.ColumnName = (string)row["ColumnName"];
column.ColumnOrdinal = (int)row["ColumnOrdinal"];
column.ColumnSize = (int)row["ColumnSize"];
column.IsIdentity = (bool)row["IsIdentity"];
column.IsUnique = (bool)row["IsUnique"];
//Get the C# type of data
object obj = row["DataType"];
Type runtimeType = obj.GetType();
System.Reflection.PropertyInfo propInfo = runtimeType.GetProperty("UnderlyingSystemType");
column.type = (Type)propInfo.GetValue(obj, null);
//Set a string so we can serialize properly later on
column.DataTypeFullName = column.type.FullName;
//I believe this is SQL Server Data Type
column.SQLServerDataTypeName = (string)row["DataTypeName"];
//Do something with the column
}
}
}

How do I extract data from a DataTable?

I have a DataTable that is filled in from an SQL query to a local database, but I don't know how to extract data from it.
Main method (in test program):
static void Main(string[] args)
{
const string connectionString = "server=localhost\\SQLExpress;database=master;integrated Security=SSPI;";
DataTable table = new DataTable("allPrograms");
using (var conn = new SqlConnection(connectionString))
{
Console.WriteLine("connection created successfuly");
string command = "SELECT * FROM Programs";
using (var cmd = new SqlCommand(command, conn))
{
Console.WriteLine("command created successfuly");
SqlDataAdapter adapt = new SqlDataAdapter(cmd);
conn.Open();
Console.WriteLine("connection opened successfuly");
adapt.Fill(table);
conn.Close();
Console.WriteLine("connection closed successfuly");
}
}
Console.Read();
}
The command I used to create the tables in my database:
create table programs
(
progid int primary key identity(1,1),
name nvarchar(255),
description nvarchar(500),
iconFile nvarchar(255),
installScript nvarchar(255)
)
How can I extract data from the DataTable into a form meaningful to use?
The DataTable has a collection .Rows of DataRow elements.
Each DataRow corresponds to one row in your database, and contains a collection of columns.
In order to access a single value, do something like this:
foreach(DataRow row in YourDataTable.Rows)
{
string name = row["name"].ToString();
string description = row["description"].ToString();
string icoFileName = row["iconFile"].ToString();
string installScript = row["installScript"].ToString();
}
You can set the datatable as a datasource to many elements.
For eg
gridView
repeater
datalist
etc etc
If you need to extract data from each row then you can use
table.rows[rowindex][columnindex]
or
if you know the column name
table.rows[rowindex][columnname]
If you need to iterate the table then you can either use a for loop or a foreach loop like
for ( int i = 0; i < table.rows.length; i ++ )
{
string name = table.rows[i]["columnname"].ToString();
}
foreach ( DataRow dr in table.Rows )
{
string name = dr["columnname"].ToString();
}
The simplest way to extract data from a DataTable when you have multiple data types (not just strings) is to use the Field<T> extension method available in the System.Data.DataSetExtensions assembly.
var id = row.Field<int>("ID"); // extract and parse int
var name = row.Field<string>("Name"); // extract string
From MSDN, the Field<T> method:
Provides strongly-typed access to each of the column values in the
DataRow.
This means that when you specify the type it will validate and unbox the object.
For example:
// iterate over the rows of the datatable
foreach (var row in table.AsEnumerable()) // AsEnumerable() returns IEnumerable<DataRow>
{
var id = row.Field<int>("ID"); // int
var name = row.Field<string>("Name"); // string
var orderValue = row.Field<decimal>("OrderValue"); // decimal
var interestRate = row.Field<double>("InterestRate"); // double
var isActive = row.Field<bool>("Active"); // bool
var orderDate = row.Field<DateTime>("OrderDate"); // DateTime
}
It also supports nullable types:
DateTime? date = row.Field<DateTime?>("DateColumn");
This can simplify extracting data from DataTable as it removes the need to explicitly convert or parse the object into the correct types.
Please consider using some code like this:
SqlDataReader reader = command.ExecuteReader();
int numRows = 0;
DataTable dt = new DataTable();
dt.Load(reader);
numRows = dt.Rows.Count;
string attended_type = "";
for (int index = 0; index < numRows; index++)
{
attended_type = dt.Rows[indice2]["columnname"].ToString();
}
reader.Close();
Unless you have a specific reason to do raw ado.net I would have a look at using an ORM (object relational mapper) like nHibernate or LINQ to SQL. That way you can query the database and retrieve objects to work with which are strongly typed and easier to work with IMHO.
var table = Tables[0]; //get first table from Dataset
foreach (DataRow row in table.Rows)
{
foreach (var item in row.ItemArray)
{
console.Write("Value:"+item);
}
}
Please, note that Open and Close the connection is not necessary when using DataAdapter.
So I suggest please update this code and remove the open and close of the connection:
SqlDataAdapter adapt = new SqlDataAdapter(cmd);
conn.Open(); // this line of code is uncessessary
Console.WriteLine("connection opened successfuly");
adapt.Fill(table);
conn.Close(); // this line of code is uncessessary
Console.WriteLine("connection closed successfuly");
Reference Documentation
The code shown in this example does not explicitly open and close the
Connection. The Fill method implicitly opens the Connection that the
DataAdapter is using if it finds that the connection is not already
open. If Fill opened the connection, it also closes the connection
when Fill is finished. This can simplify your code when you deal with
a single operation such as a Fill or an Update. However, if you are
performing multiple operations that require an open connection, you
can improve the performance of your application by explicitly calling
the Open method of the Connection, performing the operations against
the data source, and then calling the Close method of the Connection.
You should try to keep connections to the data source open as briefly
as possible to free resources for use by other client applications.

How does one loop through DataRow to retrieve set of related columns i.e (Param Name, Param Type, and Param Value)?

I'm working on a Generic Reporting Tool, where each report is represented by a row in Reports table in database.
Report row structure:
ReportID ReportFileName
RepParam1Name RepParam1Type RepParam1Value
RepParam2Name RepParam2Type RepParam2Value ... RepParam10
So, I need to retrieve report parameters (Name, Type, and Value) and loop through them to pass them to report?
FYI: Parameter Type: Date or String.
I'm using CrystalReport designer embedded with VS.NET 2005.
Okay, so while I don't know exactly what you are heading for, I will just give you an example of what I did and you can take it or leave it.
A few details for you. This is an example of connecting to an Access Databse, but connections to other kinds of databases are similar in their connection strings. Look up connection strings for the correct syntax.
I also have a strongly typed DataSet called currentDataSet and a table defined that is named the same and structured the same as the database type. There are other ways of accomplishing this, but this is the way I did it:
string conString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + sourceString;
string strSql1 = "SELECT * FROM ReportTable";
OleDbConnection con = new OleDbConnection(conString);
con.Open();
OleDbDataAdapter dAdapter = new OleDbDataAdapter();
dAdapter.SelectCommand = new OleDbCommand(strSql1, con);
dAdapter.Fill(currentDataSet, "ReportTable");
con.Close();
From there you can manipulate the data inside of the dataset. Again here is an example:
int reportTableCount = currentDataSet.ReportTable.Count();
int reportTableCounter = 0;
while (reportTableCounter < reportTableCount)
{
if (currentDataSet.ReportTable[reportTableCounter].RepParam1Value == "Bad data")
{
currentDataSet.ReportTable[reportTableCounter].RepParam1Value = "Good data";
}
reportTableCounter = reportTableCounter + 1;
}
From this point you can now update the data in the database with the following code:
con.Open();
dAdapter.SelectCommand = new OleDbCommand(strSql1, con);
OleDbCommandBuilder objCommandBuilder = new OleDbCommandBuilder(dAdapter);
dAdapter.Update(currentDataSet, "ReportTable");
con.Close();
Like I said, if none of this helps you, feel free to disregard it, you won't hurt my feelings :)
When you say loop through a DataRow do you mean sommething like:
DataRow drMyrow = MyTables.Rows[0];
foreach (DataColumn dc in drMyRow)
{
//do something with the column
}

Categories

Resources