Unable to select values when using a parameter for the column name - sql

Try
Using connection As New SqlConnection(ConnectionString)
connection.Open()
SQL = "SELECT #PARAM FROM SystemOps"
sqlCmd = New SqlClient.SqlCommand(SQL, connection)
sqlCmd.Parameters.Add(New SqlClient.SqlParameter("#PARAM", SqlDbType.VarChar)).Value = "SystemNavn"
' .. and so on...
When I run the code, it returns with a result of "SystemNavn" (which is the name of the column in the table), instead of the value of that column in the current row. What am I doing wrong?

You cannot use parameter names for column names, or any other SQL syntax. You can only use parameters as placeholders for literal values. Parameters always get replaced with the literal form for the value, so in your example, the command which is being run, essentially, gets evaluated as:
SELECT 'SystemNavn` FROM SystemOps
In order to have a variable column name, like that, I would recommend dynamically building the SQL string, like this:
Dim columnName As String = "SystemNavn"
SQL = "SELECT [" & columnName & "] FROM SystemOps"
However, by doing so, you are opening yourself up to potential SQL-injection attacks, so you need to be careful. The safest way, that I'm aware of, to avoid an attack in a situation like this is to get the list of column names from the database and compare the columnName variable against that list to ensure that it is actually a valid column name.
Of course, if the column name never changes, then there's no reason to make it a variable at all. In that case, just hard-code it directly into the SQL command, thereby avoiding the necessity for parameters or variables at all:
SQL = "SELECT SystemNavn FROM SystemOps"

Your query doesn't need any parameters in this case. just do
SQL = "SELECT SystemNavn FROM SystemOps"
This is secure. If later you need to filter this, you can do something like:
SQL = "SELECT SystemNavn FROM SystemOps WHERE COL_A = #ColA"
FYI, for your code above, since it is a VARCHAR type, it is being executed like so:
SELECT 'SystemNavn' FROM SystemOps
That is why you're getting 'SystemNavn' back.

You cannot use a parameter to specify the name of a column or a table.
The parameters collection are used to specify the values to search for, to insert, to update or delete.
Your code should be changed to something like this
Using connection As New SqlConnection(ConnectionString)
connection.Open()
SQL = "SELECT SystemNavn, <other fiels if needed> " & _
"FROM SystemOps WHERE <keyfield_name> = #PARAM"
sqlCmd = New SqlClient.SqlCommand(SQL, connection)
sqlCmd.Parameters.AddWithValue("#PARAM", paramValue)
......
End Using
Of course the example above assumes that you have a WHERE clause, if you want to retrieve every value of the column SystemNavn without condition, then you don't need a parametrized query because every part of your sql command is provided by you and there is no worry for sql injection.

Related

Is that possible that access to a sql table with question mark?

I have 3 sql tables customer, employee and manager. I want to access dynamically to my tables. I had a statement like this,
"update customer set AMOUNT where ID= ?"
But in this situation i can only access to customer. I need to access all of the tables for different operations. Is that possible to write this,
"update ? set AMOUNT where ID=?"
or what can i do to access for example employee for a different class.
The parameters can be used only in the place where you could otherwise use a literal value, like a quoted string or a numeric value.
Parameters cannot be used for identifiers like table names. Nor expressions. Nor SQL keywords.
All those other parts of the query must be fixed in the SQL query string before you prepare the query.
To query other tables, you just have concatenate the table name into the string.
String query = "update " + tableName + " set amount where ID=?";
It's up to you to make sure your variable tableName in fact only contains one of your table names. A good way to do this is to compare it to a list of known table names, and if it isn't in the list, throw an exception.

How to use variable (datatable) in sql command text to execute

I am new to Vertica and trying this in angular aspx page.
`con.Open();
cmd = con.CreateCommand();
cmd.Connection = con;
cmd.Parameters.Add(new VerticaParameter("#tblCustomers", table));
cmd.CommandText = "insert into customers select * from #tblCustomers";
cmd.ExecuteNonQuery();`
I have established the connection and inserted some fresh records too.
But Now I am trying to insert bulk records in my vertica database's table.
Something Same like SqlServer,
I have loaded my table data into "table" variable. Which is a datatable.
Is it possible to do like this ?? As I am getting some error
"
Incorrect syntax at or near $1"
customers and #tblCustomers both have same columns.
Thanks!
Setting aside whether or not you should do something like this, in the code that you've posted you're passing #tblCustomers as a parameter to the query, so it's going to treat it as a string value, not an object name in the query. You need to build the CommandText in your code without that as a parameter. Something like:
cmd.CommandText = "insert into customers select * from " & tableName
(Sorry if that syntax isn't quite right, but hopefully it gets across the point)
Some additional (and important) notes though:
Always use a column list when doing an INSERT. Use INSERT INTO MyTable (some_column, some_other_column) SELECT... not INSERT INTO MyTable SELECT...
NEVER use SELECT *. List out your column names.

SQL Query in Access to prompt with Message Box asking to change table name

Is there a way to be prompted before you a run an SQL query in Access, to enter in the table name that you wish to query? For example, lets say the columns will always stay constant. The columns could be called "Fruit" and "Date." But, the table name could change depending on the batch number. Ie. table name could be "BatchNO_1" or "BatchNO_2" or "BatchNO_3" etc. So Lets say i have an SQL like:
select Fruit, Date from BatchNO_1 where Fruit = "Apples"
Is there a way that I can be prompted to enter in the table name and have the SQL use the table name i enter to perform the query?
No. The table name cannot be passed as parameter to a query. You will have to construct the query yourself.
Dim tableName as String, sql As String
tableName = InputBox("Please enter the table name")
If tableName <> "" Then
sql = "SELECT Fruit, Date FROM [" & tableName & "] WHERE Fruit = 'Apples'"
'TODO: execute the query here
End If
For instance, you could change the query text of an existing query like this:
CurrentDb.QueryDefs("myQuery").SQL = sql
Or you could execute the query like this
Dim db As DAO.Database, rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset(sql)
Do Until rs.EOF
Debug.Print rs!Fruit & " " & rs!Date
rs.MoveNext
Loop
rs.Close: Set rs = Nothing
db.Close: set db = Nothing
By putting the batch number in the table name instead of as a column, you are encoding data in the schema. This is not best practice, so in my opinion, the correct answer is to change your database design.
Make a single Batch table with all the columns from your current BatchNo tables, but add a column named BatchNo as part of the primary key. Load all the data from your BatchNo tables into this one, and then delete those tables. Then your query will straightforwardly look like this:
SELECT Fruit, Date
FROM Batch
WHERE
Fruit = "Apples"
AND BatchNo = [Enter Batch No];
Don't put data in table names. That is not the way databases are supposed to be made.
Just to explain a little bit, the reason that your current design violates best practice is due to exactly the problem you are facing now--the shenanigans and weird things you have to do to work with such a design and try to perform operations in a reasonable, data-driven, way.
By having the user enter the table name, you also create the danger of SQL injection if you aren't also careful to compare the user-provided table name to a whitelist of allowed table names. While this may not be such a big deal in Access, it is still heading down the wrong path and is training for something else besides professional database work. If you would ever like to grow your career, it would be regrettable to first have to unlearn a bunch of stuff before you could even start with a "clean slate" to learn the right way to do things.

Using a query to loop through tables that are similar in structure but have different names

I would like to use a query to loop through tables that are similar in structure but have different names (ie. tableJan2011, tableFeb2011, tableMar2011 etc.)
Is there a way in MS Access and in SQL Server to use the same query statement while varying the table name within it. (similar to using parameter values) (need this to add different input to each different month's table)
This is a bad table design. You should have a singe table, where you have a column(s) to indicate month/year. You would then just query this single table and add a WHERE month='X' and YEAR='Y' to limit your results to what you need.
without a table redesign use UNION and clever WHERE clause parameters, which will cause rows to only come from the table that applies.
SELECT
..
FROM tableJan2011
where...
UNION
SELECT
..
FROM tableFeb2011
where...
UNION
SELECT
..
FROM tableMar2011
where...
First off, listen to the people who are telling you to use one table. They know of which they speak.
If you can't do that for some obscure reason (such as inheriting the design & not being allowed to change it), then you're stuck writing VBA code. There's no way that I know of, in Access, to substitute source tables (or even source columns--values only), in a saved QueryDef.
You'll need something like this:
Private Function QueryTable (strTableName as String) As DAO.Recordset
Const theQuery as String = "SELECT tbl.* FROM [table] As tbl"
Dim sSql As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
sSql = Replace(theQuery, "[table]", strTableName)
Set db = CurrentDb()
Set rs = db.OpenRecordset(sSql)
Set QueryTable = rs
End Function
Note that this is simplified code. There's no error handling, I haven't released the objects (which I usually do, even though they'll go out of scope), and SELECT * is almost always a bad idea.
You'd then call this function wherever you need it, passing in the name of the table.
consider moving the year and month out of the table name and into columns in one table.
you can create a table with query or table names to use at runtime, but you have to be able to write Access BASIC code in a module.
Here's an example, assuming you have a query built on a table with the query names you want to execute:
Set db = CurrentDb
Set rsPTAppend = db.OpenRecordset("qry_PTAppend")
rsPTAppend.MoveFirst
Do Until rsPTAppend.EOF
qryPT = rsPTAppend("PT")
Set qdef = db.QueryDefs(qryPT)
sqlOld = qdef.sql
sqlNew = sqlOld
' manipulate sql
If sqlNew <> sqlOld Then
qdef.sql = sqlNew
End If
db.QueryDefs(rsPTAppend("append")).Execute
If sqlNew <> sqlOld Then
qdef.sql = sqlOld
End If
rsPTAppend.MoveNext
Loop
Don't know what is possible in Access but in SQL Server you could create a view that use union to get all tables together and then build your queries against the view.
One other option you have could be to build your queries dynamically.
In sql server you can execute a string as sql.
http://msdn.microsoft.com/en-us/library/ms175170.aspx
I'm not aware of anything similar in MS Access (though my experience is limited). You could however dynamically generate your sql in code to accomplish this. Perhaps you could create a function to take the table suffix and parameters and build the desired sql that way.

What does a question mark represent in SQL queries?

While going through some SQL books I found that examples tend to use question marks (?) in their queries. What does it represent?
What you are seeing is a parameterized query. They are frequently used when executing dynamic SQL from a program.
For example, instead of writing this (note: pseudocode):
ODBCCommand cmd = new ODBCCommand("SELECT thingA FROM tableA WHERE thingB = 7")
result = cmd.Execute()
You write this:
ODBCCommand cmd = new ODBCCommand("SELECT thingA FROM tableA WHERE thingB = ?")
cmd.Parameters.Add(7)
result = cmd.Execute()
This has many advantages, as is probably obvious. One of the most important: the library functions which parse your parameters are clever, and ensure that strings are escaped properly. For example, if you write this:
string s = getStudentName()
cmd.CommandText = "SELECT * FROM students WHERE (name = '" + s + "')"
cmd.Execute()
What happens when the user enters this?
Robert'); DROP TABLE students; --
(Answer is here)
Write this instead:
s = getStudentName()
cmd.CommandText = "SELECT * FROM students WHERE name = ?"
cmd.Parameters.Add(s)
cmd.Execute()
Then the library will sanitize the input, producing this:
"SELECT * FROM students where name = 'Robert''); DROP TABLE students; --'"
Not all DBMS's use ?. MS SQL uses named parameters, which I consider a huge improvement:
cmd.Text = "SELECT thingA FROM tableA WHERE thingB = #varname"
cmd.Parameters.AddWithValue("#varname", 7)
result = cmd.Execute()
The ? is an unnamed parameter which can be filled in by a program running the query to avoid SQL injection.
The ? is to allow Parameterized Query. These parameterized query is to allow type-specific value when replacing the ? with their respective value.
That's all to it.
There are several reasons why it's good practice to use Parameterized Queries. In essence, it's easier to read and debug, and circumvents SQL injection attacks.
It's a parameter. You can specify it when executing query.
I don't think that has any meaning in SQL. You might be looking at Prepared Statements in JDBC or something. In that case, the question marks are placeholders for parameters to the statement.
It normally represents a parameter to be supplied by client.