I'm using the MySQL Connector/C++ library to insert values into a database table. I'm following the examples at
http://dev.mysql.com/tech-resources/articles/mysql-connector-cpp.html
almost exactly. However, I can't seem to get prepared statements to work with value placeholders.
sql::mysql::MySQL_Driver* driver = sql::mysql::MySQL_Driver::Instance();
boost::shared_ptr<sql::Connection> conn(driver->connect("localhost", "", ""));
conn->setSchema("TESTDB");
boost::shared_ptr<sql::Statement> stmt(conn->createStatement());
stmt->execute("DROP TABLE IF EXISTS TESTTBL");
stmt->execute("CREATE TABLE TESTTBL (m_id INT)");
boost::shared_ptr<sql::PreparedStatement> pstmt(conn->prepareStatement("INSERT INTO TESTTBL VALUES(?)"));
for (int i = 0; i != 10; ++i) {
pstmt->setInt(1, i);
pstmt->executeUpdate(); // Always inserts 0.
}
Any ideas on why I can't bind to the prepared statement? The other set* functions have the same result (e.g. if I use setString I get a string '0' in the resulting row).
I haven't done SQL in a while, but I think you're forgetting to put the column name there. The syntax should be:
INSERT INTO TESTTBL (column_name) VALUES (?)
If you wanted to insert into multiple columns, you'd use comma delimiters:
INSERT INTO TESTTBL (col1, col2, col3) VALUES (?,?,?)
Recompiling the C++ connector from source fixed this problem.
Probably a compiler setting in their pre-built binary that didn't agree with my project. I will talk to MySQL about this.
Thanks for the assistance.
Related
IDENTIFIER
31-03-2022_13636075
01-04-2022_13650262
04-04-2022_13663174
05-04-2022_13672025
20220099001
11614491_R
10781198
00000000000
11283627_P
11614491_R
-1
how can i remove (only) the "XX-XX-XXXXX_" Part in certain values of a column in SSIS but WITHOUT affecting values that doesn't have this format? For example "21-05-2022_12345678" = "12345678" but the other values i don't want them affected. This are just examples of many rows from this column so i want only the ones that have this format to be affected.
SELECT REVERSE(substring(REVERSE('09-03-2022_13481330'),0,CHARINDEX('_',REVERSE('09-03-2022_13481330'),0)))
result
13481330
but this also affects others values.Also this is in ssms not ssis because i am not sure how to transform this expression in ssis code.
Update : Corrected code in SSIS goes as following:
(FINDSTRING(IDENTIFIER,"__-__-____[_]",1) == 1) ? SUBSTRING(IIDENTIFIER,12,LEN(IDENTIFIER) - 11) : IDENTIFIER
Do you have access to the SQL source? You can do this on the sql by using a LIKE and crafting a match pattern using the single char wildcard _ please see below example
DECLARE #Value VARCHAR(50) = '09-03-2022_13481330'
SELECT CASE WHEN #Value LIKE '__-__-____[_]%' THEN
SUBSTRING(#Value,12,LEN(#Value)-11) ELSE #Value END
Please see the Microsoft Documentation on LIKE and using single char wildcards
If you don't have access to the source SQL it gets a bit more tricky as you might need to use regex in a script task or maybe there is a expression you can apply
I have a column tags containing ids in a comma separated list.
I want to search all rows where a given value is in that column.
Say I have two rows where the column tags looks like this:
Row1: 1,2,3,4
Row2: 2,5,3,12
and I want to search for a row where the column contains a 1. I try to do it this way:
$qb = $this->createQueryBuilder('p')
->where(':value IN (p.tags))
->setParameter('value', 1);
I expect it to do something like
SELECT p.* FROM mytable AS p WHERE 1 IN (p.tags)
Executing this in MySQL directly works perfectly. In Doctrine it does not work:
Error: Expected Literal, got 'p'
It works the other way around, though, but this is not what I need:
->where("p.tags IN :value")
I've tried a lot to make this work, but it just won't... Any ideas?
I think you should use the LIKE function for each scenario, as example:
$q = "1";
$qb = $this->createQueryBuilder('p')
->andWhere(
$this->expr()->orX(
$this->expr()->like('p.tags', $this->expr()->literal($q.',%')), // Start with...
$this->expr()->like('p.tags', $this->expr()->literal('%,'.$q.',%')), // In the middle...
$this->expr()->like('p.tags', $this->expr()->literal('%,'.$q)), // End with...
),
);
See the SQL statement result in this fiddle
Hope this help
I am using JSON format to save data in my c++ program , i want to send it to MySql database (the table tab has one column with type : TEXT) but the query failed (tested also VARCHAR and CHAR )
this is a part of the code since we are not interrested in the rest
string json_example = "{\"array\":[\"item1\",\"item2\"], \"not an array\": \"asdf\"}";
mysql_init(&mysql); //initialize database connection
string player="INSERT INTO tab values (\"";
player+= json_example;
player += "\")";
connection = mysql_real_connect(&mysql,HOST,USER,PASSWD,DB,0,NULL,0);
// save data to database
query_state=mysql_query(connection, player.c_str()); // use player.c_str()
to show the final query that will be used : cout << player gives :
INSERT INTO tab values ("{"array":["item1","item2"], "not an
array": "asdf"}")
using for example string json_example = "some text"; is working
but with the json format it is not working , maybe the problem came from the use of curly bracket {} or double quotes "" but i haven't find a way to solve it .
i'm using :
mysql Ver 14.14 Distrib 5.5.44, for debian-linux-gnu (armv7l) under raspberry pi 2
Any help will be appreciated , thanks .
Use a prepared statement. See prepared statements documentation in the MySQL reference manual.
Prepared statements are more correct, safer, possibly faster, and keep your code cleaner. You get all those benefits and don't need to escape anything. There is hardly a reason not to use them.
Something like this might work. But take it with a grain of salt, because I have not tested or compiled it. It should just give you the general idea:
MYSQL_STMT* const statement = mysql_stmt_init(&mysql);
std::string const query = "INSERT INTO tab values(?)";
mysql_stmt_prepare(statement, query, query.size());
MYSQL_BIND bind[1] = {};
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = json_example.c_str();
bind[0].buffer_length = json_example.size();
mysql_stmt_bind_param(statement, bind);
mysql_stmt_execute(statement);
I want to select all the binary data from a column of a SQL database (SQL Server Enterprise) using C++ query. I'm not sure what is in the binary data, and all it says is .
I tried this (it's been passed onto me to study off from) and I honestly don't 100% understand the code at some parts, as I commented):
SqlConnection^ cn = gcnew SqlConnection();
SqlCommand^ cmd;
SqlDataAdapter^ da;
DataTable^ dt;
cn->ConnectionString = "Server = localhost; Database=portable; User ID = glitch; Pwd = 1234";
cn->Open();
cmd=gcnew SqlCommand("SELECT BinaryColumn FROM RawData", cn);
da = gcnew SqlDataAdapter(cmd);
dt = gcnew DataTable("BinaryTemp"); //I'm confused about this piece of code, is it supposed to create a new table in the database or a temp one in the code?
da->Fill(dt);
for(int i = 0; i < dt->Rows->Count-1; i++)
{
String^ value_string;
value_string=dt->Rows[i]->ToString();
Console::WriteLine(value_string);
}
cn->Close();
Console::ReadLine();
but it only returns a lot of "System.Data.DataRow".
Can someone help me?
(I need to put it into a matrix form after I extract the binary data, so if anyone could provide help for that part as well, it'd be highly appreciated!)
dt->Rows[i] is indeed a DataRow ^. To extract a specific field from it, use its indexer:
array<char> ^blob=dt->Rows[i][0];
This extracts the first column (since you have only one) and returns an array representation of it.
To answer the question in your code, the way SqlDataAdapter works is like this:
you build a DataTable to hold the data to retrieve. You can fill in its columns, but you're not required to. Neither are you required to give it a name.
you build the adapter object, giving it a query and a connection object
you call the Fill method on the adapter, giving it the previously created DataTable to fill with whatever your query returns.
and you're done with the adapter. At this point you can dispose of it (for example inside a using statement if you're using C#).
I wonder if there is an easy and efficient way in SQL Server 2005 to eliminate replicated characters in a string. Like converting
'ABBBCDEEFFFFG' to 'ABCDEFG'
It really sucks that SQL Server has such a poor string library and no ready-to-use regexp feature...
You can use the CLR functionality built into SQL Server 2005/2008 to get this done by .NET code.
MSDN magazine wrote about it in their February 2007 issue.
If this is not an acceptable solution, here is a UDF that will do the same, mind you this is about two orders of magnitude slower than the CLR solution.
YMMV. This appears to work for your string above. But not ABBBCDEEBBBBG
DECLARE #Numbers TABLE (Num smallint NOT NULL PRIMARY KEY)
INSERT #Numbers (Num)
SELECT TOP 8000
ROW_NUMBER() OVER (ORDER BY c1.NAME)
FROM
sys.columns c1
DECLARE #STuff TABLE (Seq varchar(100) NOT NULL PRIMARY KEY)
INSERT #STuff (Seq) VALUES ('ABBBCDEEFFFFG') --works
SELECT
Single
FROM
(
SELECT DISTINCT
CAST(Single AS varchar(100))
FROM
#Numbers N
CROSS APPLY
(SELECT Seq, SUBSTRING(Seq, Num, 1) AS Single FROM #Stuff) S
WHERE
Num <= LEN(Seq)
FOR XML PATH ('')
) foo(Single)
I know about the CLR solution, but as I said, I am neither responsible nor authorized to implement it in the DB of question.
For this particular problem, I decided to write a very simple and kinda silly loop. I am afraid it won't be fast enough for millions of records, but anyways... I wish I could do this stuff in the application layer but I am bound to T-SQL here..
DECLARE #i int ; -- counter
DECLARE #input varchar(200) ;
SET #input = 'AAABCDEEFFBBBXYZSSSWWWNT'
IF LEN(#input) > 1
BEGIN
DECLARE #unduplicated varchar(200) ;
SET #unduplicated = SUBSTRING(#input,1,1) ;
SET #i = 2 ;
WHILE #i <= LEN(#input)
BEGIN
-- If current char is different from the last char, concatenate, else not
IF SUBSTRING(#unduplicated, LEN(#unduplicated), 1) <> SUBSTRING(#input, #i, 1)
SET #unduplicated = #unduplicated + SUBSTRING(#input, #i, 1) ;
SET #i = #i + 1;
END
END
SELECT #unduplicated AS unduplicated;
Result:
unduplicated
ABCDEFBXYZSWNT