I'm trying to read tables in an SQL statement. The names of the Tables, are pulled in a listbox.
Users will select the name of the table they want to view the data for, and in turn my method will read+visualize+export that table.
The issue is with the name of the table as a dynamic value. Initially I wrote the code in IronPython, and was ok.
Now I'm translating this to C# and I face a syntax issue (obviously, the server address/login posted here, are not the real ones).
The tables names are populated in listBox1 from a separate method.
private void rEADSELECTEDTABLE_Click(object sender, EventArgs e)
{
string tableName = listBox1.GetItemText(listBox1.SelectedItem);
MessageBox.Show(" Table Selected: " + tableName);
try
{
string sqlConnectionString;
myConnectionString = #"server=000.00.000.0;database=myDatabase;uid=myUser;password=myPassword";
mySQL = new SqlConnection(myConnectionString);
mySQL.Open();
SqlCommand myCommand2 = new SqlCommand("SELECT * FROM #myTable", mySQL);
SqlParameter param = new SqlParameter();
param.ParameterName = "#myTable";
param.Value = tableName;
myCommand2.Parameters.Add(param);
SqlDataAdapter myAdapter = new SqlDataAdapter();
myAdapter.SelectCommand = myCommand2;
DataSet dataSet = new DataSet();
myAdapter.Fill(dataSet);
List<string> rows = new List<string>();
List<string> rowData = new List<string>();
foreach (DataTable table in dataSet.Tables)
foreach (DataRow row in table.Rows)
foreach (DataColumn column in table.Columns)
if (row[column] != null)
rowData.Add(row[column].ToString());
foreach (String s in rowData)
Console.WriteLine(s);
mySQL.Close();
}
}
When I run the code I get this error:
System.Data.SqlClient.SqlException (0x80131904): Must declare the table variable "#myTable".
If I use a static table name, everything works well.
SqlCommand myCommand2 = new SqlCommand("SELECT * FROM TABLE_NAME", mySQL);
SqlDataAdapter myAdapter = new SqlDataAdapter();
myAdapter.SelectCommand = myCommand2;
Help greatly appreciated.
you cannot use TableName as a parameter with SqlCommand
change the sql query, somthig like :
SqlCommand myCommand2 = new SqlCommand("SELECT * FROM " + tableName, mySQL);
OR
SqlCommand myCommand2 = new SqlCommand(string.Format("SELECT * FROM {0}", tableName), mySQL);
but be careful from sql injection attack !
another way is to work with dynamic sql query using stored procedure and send the table name as a parameter
Related
I’ve two comboboxes which should contain two different informations.
1.cb1: select table_name from information_schema.tables (this display multiple tables)
2.cb2: should populate it with a column name.
Example: I've three tables in cb1 with the same attributes but have different values at the column EmpName (tblLondon,tblBerlin,tblRom,...)
Now I wanna display in second comboboxe the column EmpName dynamically whenever I choose a table in first combobox.
cb1[tblLondon] cb2[John,Mavis,Chris,Mike..]
OR
cb1[tblBerlin] cb2[Günther,Peter, Sophie,Sunny, ..]
Can u plz help me out
string C = ConfigurationManager.ConnectionStrings[""].ConnectionString;
SqlConnection con = new SqlConnection(C);
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = ("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_NAME ASC");
try
{
// Open connection, Save the results in the DT and execute the spProc & fill it in the DT
con.Open();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
dt = new DataTable();
adapter.Fill(dt);
cbTbl.DisplayMember = "TABLE_NAME";
cbTbl.ValueMember = "TABLE_NAME";
//Fill combobox with data in DT
cbTbl.DataSource = dt;
// Empty bzw. clear the combobox
cbTbl.SelectedIndex = -1;
This code is working and populating my cb1 (combobox)
And now i don't really know how to go about with cb2
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
}
if I understand you correctly, and if you have this data in SQL server or other database you should use SelectedIndexChange event and load item for that Id (use Display Member and Value Member for match Id).
take a look at this.it might help you
Edit :
you can do this with below code : (if you don't use database)
you should use this code in cb1.SelectedIndexChange (or value)
var cb2items = new Dictionary<int, string> {{1, "Name"}, {1, "anotherName"},{2,"Name"},{2, "anotherName"}}; // use the number for parent Id in cb1
foreach (var item in cb2items)
{
if (item.Key == int.Parse(comboBox1.SelectedValue.ToString()))
{
comboBox2.Items.Add(item);
}
}
Edit 2 :
use this code in cb1.SelectedValueChange:
string C = ConfigurationManager.ConnectionStrings[""].ConnectionString;
SqlConnection con = new SqlConnection(C);
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = ("SELECT ... WHERE TableName = cb1.SelectedValue");
spProc & fill it in the DT
con.Open();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
dt = new DataTable();
adapter.Fill(dt);
cbTbl.DisplayMember = "TABLE_NAME";
cbTbl.ValueMember = "TABLE_NAME";
cbTb2.DataSource = dt;
and you also can create a procedure that send back the items from table name as input. if you use procedure, your code perform better.
Edit 3 :
put this code in cbTb2.SelectedValueChange event :
try
{
int a = int.Parse(cbTB2.SelectedValue.ToString());
}
catch { }
You might want to see combobox's events, "SelectedIndexChanged" or "SelectedValueChanged" should do it
I have created a table name glossary in a database named ChatBotDataBase in SQL Server. I want to read the data in a special column of the table.
To do so, I have written this code:
private void button1_Click(object sender, EventArgs e)
{
SqlConnection sc = new SqlConnection();
sc.ConnectionString = #"Data Source=shirin;Initial Catalog=ChatBotDataBase;
Integrated Security=True";
SqlDataAdapter sda = new SqlDataAdapter();
sda.SelectCommand = new SqlCommand();
sda.SelectCommand.Connection = sc;
sda.SelectCommand.CommandText = "SELECT * FROM glossary";
DataTable table = new DataTable();
MessageBox.Show(table.Rows[0].ItemArray[3].ToString());
}
But there is an error in last line.
The error is :
An unhandled exception of type 'System.IndexOutOfRangeException' occurred in System.Data.dll.
And here is a print screen of the mentioned table:
Can anyone help please?
Looks like you are confusing the Datatable called table with your database table in your sql server. In your image you show us the glossary table in your sql server, not the DataTable called table.
You get this error because you create an empty DataTable called table with DataTable table = new DataTable() but you didn't even fill your table. That's why it doesn't have any rows by default.
SqlCommand cmd = new SqlCommand("SELECT * FROM glossary");
SqlDataAdapter sda = new SqlDataAdapter(cmd);
sda.Fill(table);
Also use using statement to dispose your SqlConnection, SqlCommand and SqlDataAdapter.
using(SqlConnection sc = new SqlConnection(conString))
using(SqlCommand cmd = sc.CreateCommand())
{
cmd.CommandText = "SELECT * FROM glossary";
...
using(SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
DataTable table = new DataTable();
sda.Fill(table);
if(dt.Rows.Count > 0)
MessageBox.Show(table.Rows[0].ItemArray[3].ToString());
}
}
Below code will help you
sda.SelectCommand.CommandText = "SELECT * FROM glossary";
DataTable table = new DataTable();
sda.Fill(table , "glossary");
MessageBox.Show(table.Rows[0].ItemArray[3].ToString());
You haven't executed the query or populated the table. It is empty. It has no columns and no rows. Hence the error.
Frankly, though, I strongly suggest using a typed class model, not any kind of DataTable. With tools like "dapper", this can be as simple as:
var list = conn.Query<Glossary>("SELECT * FROM glossary").ToList();
With
public class Glossary {
public int Id {get;set}
public string String1 {get;set} // horrible name!
....
public int NumberOfUse {get;set}
}
Dear kindly first fill your table with the data.
And you should use checks because if there is no data then you get a proper message.check is below..
if(dt.Rows.Count > 0)
MessageBox.Show(table.Rows[0].ItemArray[3].ToString());
else if(dt.Rows.Count > 0)
MessageBox.Show("Table is empty");
And other advice is that you should display data into DataGrid.... Displaying data from Database into a message box is not a good programming approach..
For displaying DataTable into DataGrid in C# is as simple as below.
SqlCommand cmd = new SqlCommand("select * from student",con);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
DataTable dt = new DataTable();
dt.TableName = "students";
da.Fill(dt);
dataGridView1.DataSource =dt;
using System.Data.Odbc;
OdbcConnection con = new OdbcConnection("<connectionstring>");
OdbcCommand com = new OdbcCommand("select * from TableX",con);
OdbcDataAdapter da = new OdbcDataAdapter(com);
DataSet ds = new DataSet();
da.Fill(ds,"New");
DataGrid dg = new DataGrid();
dg.DataSource = ds.Tables["New"];
you can get the connection string from:
http://www.connectionstrings.com/
I am trying to delete selected data from datagrid and database at the same time when user clicks on "Delete". It is not working and error message shows that "Index was out of range. Must be non-negative and less than the size of the collection.Parameter name: index"
Can anyone help me out this coding.
private void btnDeleteCustomer_Click(object sender, EventArgs e)
{
string strSqlConnection = #"Data Source = KK\SQLEXPRESS; Integrated Security = SSPI; Initial Catalog = JeanDB";
if ((dgvCustomerView.Rows.Count>0) && (dgvCustomerView.SelectedRows[1].Index != dgvCustomerView.Rows.Count))
{
SqlConnection sqlconn = new SqlConnection(strSqlConnection);
DataSet dsCustomers = new DataSet();
int iCustomerID = Convert.ToInt32(dgvEmpView.SelectedRows[0].Cells[0].Value.ToString());
string QueryDelCus = #"Delete from dbo.Customers WHERE CustomerID = #iCustomerID";
SqlDataAdapter sdaCustomer = new SqlDataAdapter(QueryDelCus, sqlconn);
sqlconn.Open();
DataTable dtEmployee = new DataTable("Customers");
sdaCustomer.Fill(dsCustomers, "Customers");
sqlconn.Close();
dgvEmpView.Rows.RemoveAt(dgvEmpView.SelectedRows[0].Index);
MessageBox.Show("Deleted Successfully");
}
}
Instead of Remove you can rebind grid:
dgvEmpView.DataSource = dsCustomers;
dgvEmpView.DataBind();
MessageBox.Show("Deleted Successfully");
and for deletion ExecuteNonQuery is used:
SqlCommand cmd = new SqlCommand(QueryDelCus, sqlconn);
sqlconn.Open();
cmd.ExecuteNonQuery();
Unless you have two rows selected referencing the SelectedRows[1] is wrong. The array indexes start always with zero. (Probably it is just a type because the other lines references correctly the row to be deleted)
if ((dgvCustomerView.Rows.Count>0) &&
(dgvCustomerView.SelectedRows[0].Index != dgvCustomerView.Rows.Count))
{
....
but then, to delete the row in the database, you don't need to use an SqlDataAdapter.
You could work directly with a SqlCommand
int iCustomerID = Convert.ToInt32(dgvEmpView.SelectedRows[0].Cells[0].Value.ToString());
string QueryDelCus = #"Delete from dbo.Customers WHERE CustomerID = #iCustomerID";
SqlCommand cmd = new SqlCommand(QueryDelCus, sqlconn);
cmd.Parameters.AddWithValue("#iCustomerID", iCustomerID);
sqlconn.Open();
cmd.ExecuteNonQuery();
finally you could simply remove the selected row from the grid without further query
dgvEmpView.Rows.RemoveAt(dgvEmpView.SelectedRows[0].Index);
If do not use sql parameters then use plain sql query.
DataSet dsCustomers = new DataSet();
int iCustomerID = Convert.ToInt32(dgvEmpView.SelectedRows[0].Cells[0].Value.ToString());
string QueryDelCus = #"Delete from dbo.Customers WHERE CustomerID = "+ iCustomerID.ToString();
SqlDataAdapter sdaCustomer = new SqlDataAdapter(QueryDelCus, sqlconn);
How do I check if a specified column allows null values or not?
I'm using the following code to print all the columns, but I also want to print if the column allows null values:
cnn = new SqlConnection(connetionString);
cnn.Open();
SqlCommand myCommand = new SqlCommand("select * from " + tableName, cnn);
SqlDataAdapter da = new SqlDataAdapter(myCommand);
DataSet ds = new DataSet();
da.Fill(ds, tableName);
foreach (DataColumn dc in ds.Tables[0].Columns)
{
// Print stuff here, dc.ColumnName is the column name
}
The DataColumn.allowDBnull property doesn't seem to work when getting a predefined table, it's always set to true, even in columns that doesn't allow nulls.
Thanks for your time!
If you are only after column data I would do this from the system views, rather than relying on the data adapter. e.g.
DECLARE #TableName VARCHAR(50) = 'dbo.TableName'
SELECT Name, Column_ID, Is_Nullable
FROM SYS.COLUMNS
WHERE [Object_ID] = OBJECT_ID(#TableName)
This also means you can use parameterised queries properly and avoid the risks of SQL Injection. So your final code would be something like this:
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand("SELECT Name, Is_Nullable FROM sys.columns WHERE [Object_ID] = OBJECT_ID(#TableName)", connection))
{
connection.Open();
command.Parameters.Add("#TableName", SqlDbType.VarChar).Value = tableName;
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine("Name: {0}; Allows Null: {1}", reader.GetString(0), reader.GetBoolean(1));
}
}
}
SqlDataAdapter.Fill() Adds or refreshes rows and does nothing in relation to a table schema information which knows whether particular column allows null. But you can use SqlDataAdapter.FillSchema() to load schema information, then AllowsDBNull would show you a correct state of a column.
SqlDataAdapter da = new SqlDataAdapter(myCommand);
DataSet ds = new DataSet();
da.FillSchema(ds, SchemaType.Source, tableName);
da.Fill(ds, tableName);
da.FillSchema(ds, SchemaType.Source, tableName);//Loads all the constraints and relations of tables
da.Fill(ds, tableName);//Loads the data
cnn = new SqlConnection(connetionString);
cnn.Open();
SqlCommand myCommand = new SqlCommand("
select name,is_nullable from sys.columns where object_id=object_id('"+tableName+"')", cnn);
SqlDataAdapter da = new SqlDataAdapter(myCommand);
DataSet ds = new DataSet();
da.Fill(ds, tableName);
foreach (datarow in ds.Tables[0].rows)
{
if(dr["is_nullable"].ToString()==1)
//the column is nullable
else
//column is not nullable
}
I am trying to display the data from sql into a datagrid as follows:
try
{
SqlConnection xconn = new SqlConnection();
xconn.ConnectionString = #"Data Source=servername; Trusted_Connection=yes; Database=master";
xconn.Open();
string s = "select * from tablename where name=#name";
SqlCommand ycmd = new SqlCommand(s, xconn);
ycmd.Parameters.Add("#name", dropdownlistname.SelectedValue);
SqlDataAdapter da = new SqlDataAdapter(ycmd);
DataTable dt = new DataTable();
da.Fill(dt);
gridview.DataSource = dt;
gridview.DataBind();
}
catch (Exception e2)
{
lblresult.Text = e2.Message + "<br />" + e2.StackTrace ;
}
I do not get any exception . However , the grid is not displayed.
try like this....
you can change this depends on your requirement ....
SqlCommand command = new SqlCommand();
command.CommandText = "SELECT * FROM Product WHERE Product.ID=#PROD_ID";
command.Parameters.Add(new SqlParameter("#PROD_ID", 100));
// Execute the SQL Server command...
SqlDataReader reader = command.ExecuteReader();
DataTable tblProducts = new DataTable();
tblProducts.Load(reader);
foreach (DataRow rowProduct in tblProducts.Rows)
{
// Use the data...
}
It doesn't work because you are defining a parameter #name to your sql statement but you are never feeding any value since the version of SqlCommand.Parameters.Add that takes 2 parameters is the one that receives parameterName and SqlDbType
I am surprised you are not getting exceptions. Perhaps your dropdownlistname.SelectedValue matches one of the enumeration values for SqlDbType and that's why?
You should be doing:
ycmd.Parameters.AddWithValue("#name", dropdownlistname.SelectedValue);