I'm wondering if there's any way to have an if statement inside the declaration of a PL/SQL procedure. E.g:
procedure testing (no IN NUMBER, name IN VARCHAR2) IS
if no = 0 then
cursor c is
select * from table where name = name;
else
cursor c is
select * from table where name = name;
end if;
BEGIN
--work with cursor c
END testing;
This is more or less the intention of it.
No, you can only have variables declaration and initialization in the declarative part.
You can use a cursor variable (REF CURSOR type) and open the cursor from the executable block:
procedure testing (no IN NUMBER, name IN VARCHAR2) IS
TYPE YOUR_CURSOR_TYPE IS REF CURSOR;
c YOUR_CURSOR_TYPE;
BEGIN
--work with cursor c
if no = 0 then
OPEN c FOR
select * from table where name = name;
else
open c FOR
select * from table where name = name;
end if;
... do something with c
END testing;
Depending on the columns of your select clause you must decide whether using a strongly typed or weakly typed cursor variable.
Cursor Variables
Pardon, haven't read the question correctly. You can't do IF before BEGIN.
If C is ref cursor you could open it either for select * from table or select name from table as well but the intention of it isn't clear enough because you should have the possibility to deal with diffident field list in both cases.
The example from Oracle: http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/sqloperations.htm#BABFEJED
Related
I have to use a user input value in my query to select a row which has that value........
I have written this code in qt but it doesn't work...how can I fix it?
void MainWindow::on_pushButton_clicked()
{
int j=0;
float t;
t=ui->T_lineEdit->text().toFloat();
QSqlQuery qry;
if(qry.exec("select * from table where te='+t+'"))
{
ui->u_lineEdit->setText("hello");
}
}
You should use a prepared statement using QSqlQuery.
QSqlQuery qry;
qry.prepare("select * from table where te=?");
qry.addBindValue(t);
if(qry.exec())
{
ui->u_lineEdit->setText("hello");
}
Note that concatenating user's raw string to a SQL query is highly vulnerable to SQL Injection.
I'm not familliar with qt, but it seems to me that you used concatenation within a string, so "select * from table where te='+t+'" should be "select * from table where te='"+t+"'" .
Of course it is strange that you should place single quotes around a float value, but I don't know the type of column te. It could be necessary to convert t to string first:
"select * from table where te='" + QString::number(t) + "'"
Finally I have to add that this looks suspiciously like code where you allow SQL Injection. You should look into this and make sure to avoid it. See Frogatto's answer for that.
I just need a little help with file parsing. We have to parse a file that has 6 string entries per row in the format:
"string1", "string2", "string3", "string4", "string5", "string6"
My instructor recently gave us a little piece of code as a "hint," and I'm supposed to use it. Unfortunately, I can't figure out how to get it to work. Here's my file parsing function.
void parseData(ifstream &myFile, Book bookPtr[])
{
string bookInfo;
int start, end;
string bookData[6];
getline(myFile, bookInfo);
start = -2;
myFile.open("Book List.txt");
for (int j = 0; j < 6; j++)
{
start += 3;
end = bookInfo.find('"', start);
bookData[j] = bookInfo.substr(start, end-start);
start = end;
}
}
So I'm trying to read the 6 strings into an array of strings. Can someone please help walk me through the process?
start = -2;
for (int j = 0; j < 6; j++)
{
start += 3;
end = bookInfo.find('"', start);
bookData[j] = bookInfo.substr(start, end-start);
start = end;
}
So ", " is four characters. The leading closing quote is 3 characters behind the opening closing quote.
At entry to the loop start is pointing to the last closing quote. (On first entry to loop it is faked as -2 to be pointing to the closing quote of the imaginary "-1th" element.)
So we advance from the last closing quote to the following opening quote:
start += 3;
Then we use std::string::find to find the closing quote:
end = bookInfo.find('"', start);
The offset tells it to ignore all characters up to and including that position.
We then have the two quote positions, start..end, so we use substr to extract the string:
bookData[j] = bookInfo.substr(start, end-start);
And we then update start for the next loop to be the last closing quote:
start = end
Please, for your own sake, create a minimal example. This starts with a string like the line you gave as example and ends with the different parts in an array. Leave the loading from a file out for now, getline() seems to work for you, or? Then, do not declare every variable you might want to use at the beginning of a function. This is not ancient C, where you simply had to do that or introduce additional {} blocks. There is another thing odd, and that is the Book bookPtr[]. This is indeed just a Book* bookPtr, i.e. you are not passing an array to a function but just a pointer. Don't fall for this misleading syntax, it's a lie! Anyway, you don't seem to be using that pointer to the object(s) of the unknown type anyway.
Concerning the splitting of a line into strings, one approach is to locate pairs of double quotes. Everything in between is one of the strings, everything without is irrelevant. The string class has a find() function which optionally takes a starting position. Starting position is always one behind the previously found position.
Your code above seems to assume that there is exactly one double quote, a comma, a space and another double quote that separates two strings. This isn't 100% clear, I would also be prepared for handling multiple spaces or no space at all. Also, is the comma guaranteed? Are the double quotes guaranteed? Anyway, keep it simple. Unless you get a better spec on the input, just assume that only the parts between the quotes is what differs.
Then, what exactly works and what doesn't? You need to ask more specific questions and give more detailed information. The code above doesn't look broken per se, although there are a few things a bit off. For example, you don't typically pass ifstreams to a function, but use the istream baseclass. In your case, you read a line from that file and then open another file using the same fstream object, which doesn't make sense to me, since you don't use it after that. If you only needed that stream locally, you would create and open it there (handling errors of course!) and pass in the filename as parameter only.
i have the following code.My table is called 'tableu'.I want replace 'tableu' with a variable that will hold the table name. How can i represent that.
query.prepare(
"INSERT INTO tableu (village, weight, diet, age)"
"VALUES (:village, :weight, :diet, :age)"
);
If you want to change your table name from tableu to lets say NewTableName, it can be done using any of the following syntax:
query.prepare(
"RENAME tableu TO NewTableName"
);
OR
query.prepare(
"ALTER TABLE tableu RENAME TO NewTableName"
);
Update:
May be the OP is looking for this.
QString tableName = QString("tableu");
QString sqlQuery = QString("INSERT INTO %1 (village, weight, diet, age) VALUES (:village, :weight, :diet, :age)").arg(tableName);
I'm not 100% sure what you want, but this code will let you have a variable that may contain different tables names placed in the query
char sBuffer [1024];
char sQueryTable[] = "tableu";
sprintf(sBuffer , "INSERT INTO %s (village, weight, diet, age) VALUES (:village, :weight, :diet, :age)", sQueryTable);
query.prepare(sBuffer);
Read about sprinft and formatting strings here
Note: you can always use std::strings as well and concatenate the string together from a variable holding your table name and the rest of the string
Here is the problem, I dont know how many attributes or which type are the attributes in table and I need simple select statment like: SELECT * FROM TABLE1; to write down to file.
And this need to be done with otlv4 wrapper.
Please help.
otl_stream i(50, // buffer size
"select * from test_tab where f1>=:f<int> and f1<=:f*2", // SELECT statement
db // connect object
);
int ac=0;
char bc[64];
memset(bc, 0, 64);
while(!i.eof())
{
i >> ac >> bc;
cout << "Boooo " << ac << " " << bc << endl;
}
This is example where I know how many attributes are there and which type are there. But what if I dont know that??
A file stream along with OTL's check_end_of_row() and set_all_column_types() functions should do what you're asking. While looping on an OTL stream's eof check, for each row you could loop on the end of row check, and send each attribute's value from the OTL stream to the file stream. After each end of row check, send your line break code(s) to the file stream. Setting all column types to str should allow you to use just one variable to process all attribute values in a row.
This example from the OTL docs demonstrates how to use the set_all_column_types function. You must create a stream first, set the option, then open the stream. If you create and open the stream at the same time, it won't work.
I'm writing some c++ code that uses the sqlite3 library. I'm using a prepared statement to which I bind a variable at runtime.
How do I examine the SQL query in the statement after the bindings?
For example, the code below doesn't return a row. When using a premade string and sqlite3_exec, I get the results I expect.
sqlite3_stmt *statement;
const char *query = "SELECT * FROM foo WHERE (name='?');";
sqlite3_prepare_v2(db, query, strlen(query), &statemtnt, NULL);
sqlite3_bind_text(statement, 1, "bar", -1, SQLITE3_STATIC);
int result = sqlite3_step(statement);
// expected: result = SQLITE_ROW
// actual: result = SQLITE_DONE
edit: As Ferdinand stated below, the problem in the query above is the quotes around the ?. However, for the future, I'd still like to know how to inspect the sqlite3_stmt for the actual query that will be executed.
The SQL query does not change after the bindings -- your variables aren't inserted into the SQL string or anything.
In addition to what Neil said, drop the quotation marks around the ? placeholder:
"SELECT * FROM foo WHERE name = ?"
Otherwise SQLite won't replace the question mark but will treat it as the string "?".
Yes, you can do it by defining a profile function like this:
static void profile(void *context, const char *sql, sqlite3_uint64 ns) {
fprintf(stderr, "Query: %s\n", sql);
fprintf(stderr, "Execution Time: %llu ms\n", ns / 1000000);}
Then right after you open your database using sqlite3_open, make this call:
sqlite3_profile(fDBLink, &profile, NULL);
The third parameter of sqlite3_bind_text is supposed to be the value you want to bind - in your code you are trying to bind the query to itself!
Also, lose the semicolon at the end of the SELECT.
Don't know sqlite all that well, but the actual query might be logged or you might be able to flip a switch to get it to be logged.