question on JDBC TSDBPreparedStatement with TDengine - database

When using JDBC PreparedStatement::addBatch to add a SQL, the double quotes in SQL can be falsely omitted.
preparing data:
create a stable create stable stb (ts timestamp, col int) tags (nchar_tag nchar(8));
create a table using PreparedStatement:
code is following:
String sql = "create table tb using stb (nchar_tag) tags ('\"abc\"')";
Connection conn = getConn();
PreparedStatement pstmt = conn.prepareStatement(sql);
pStmt.addBatch();
pStmt.executeBatch();
conn.close();
Thene to query show
create table tb and get CREATE TABLE tb USING stb TAGS ("abc")
I think the tag should be "abc". If executing the SQL in TDengine CLI, the query gets CREATE TABLE tb USING stb TAGS (""abc"").
TDengine Version 2.4.0.7 and JDBC version taos-jdbcdriver-2.0.37 with JNI connection

Related

How to import/read a .dbf file on sqlserver 2012 using openrowset?

I have too many free tables from an old software and need to connect some of this tables to sql to tranfer the info and use in other software.
While your question is about how to do that using OpenRowSet, I would say forget about getting VFP data using OpenRowset or OpenQuery (which would be better of the two). Probably 32 bits or 64 bits import\export wizards wouldn't work either. All those were working successfully in good old times before windows 10 at least. I don't know what they have changed, now they all fail (I had tons of working OpenRowset, OpenQuery samples under windows 7).
You might try Sybase ADS driver with OpenRowset and OpenQuery.
Fortunately there are many workarounds. Some workarounds use intermediates like access and excel but IMHO they are overkill.
If you are using VFP itself, simplest would be to do this from within VFP, where it is a series of "auto generated on the fly" code executing against SQL Server.
One other option (which I favor) would be to use some C# code, that would do the transfer using "SqlBulkCopy" class. For a generic solution, you could:
Create a database on server,
Read a VFP table's Schema information,
Create compatible table on server (meaning you might want to change datatypes),
Create column mappings info,
Bulk load to table
Repeat the process in a loop for all tables.
Here is one sample that doesn't read the schema but instead creates a temp table on server with a known schema and sample mapping just for demo purposes (if you think DBF to SQL Server tools on the market are over 100$ not a bad starter):
void Main()
{
string sqlConnectionString = #"server=.\SQLExpress;Trusted_Connection=yes;Database=Test";
string path = #"C:\PROGRAM FILES (X86)\MICROSOFT VISUAL FOXPRO 9\SAMPLES\Northwind";
DataTable tbl = new DataTable(); // just to show the results - sadece sonuclari gostermek icin
using (OleDbConnection cn = new OleDbConnection("Provider=VFPOLEDB;Data Source="+path))
using (SqlConnection scn = new SqlConnection( sqlConnectionString ))
{
// Creatint a temp SQL Server table for sampling.
// If the table already existed then this part wouldn't exist.
// We would simply insert then.
// gecici bir SQL server tablosu yaratiyoruz ornek icin.
// tablo zaten var ise bu kisim olmayacak. Sadece insert edecektik.
SqlCommand createTemp = new SqlCommand();
createTemp.CommandText = #"create table ##SqlBulkSample
(
[CustomerId] char(6),
[Company] varchar(50),
[Contact] varchar(50),
[Country] varchar(20)
)";
createTemp.Connection = scn;
scn.Open();
createTemp.ExecuteNonQuery();
// Get the data from VFP and write to server using SqlBulkCopy
// Excelden veriyi al ve SqlBulkCopy ile servera yaz
OleDbCommand cmd = new OleDbCommand("select CustomerId, CompanyName, ContactName, Country from Customers", cn);
SqlBulkCopy sbc = new SqlBulkCopy(scn, SqlBulkCopyOptions.TableLock,null);
// For demonstration purposes of column mapping,
// we have different count of fields with different field names and order.
// Without mapping, it would be a copy of the same structured data
// Column mapping'i orneklemek icin farkli sayi, isim ve sirada alanlarimiz var.
// Mapping olmasa idi ayni yapidaki veri kopyalaniyor olacakti.
sbc.ColumnMappings.Add(0,"[CustomerId]");
sbc.ColumnMappings.Add(1,"[Company]");
sbc.ColumnMappings.Add(2,"[Contact]");
sbc.ColumnMappings.Add(3,"[Country]");
cn.Open();
OleDbDataReader rdr = cmd.ExecuteReader();
//SqlBulkCopy properties
//With defaults or high values we wouldn't see any notification so
// for demoing purposes setting them to be extremely low
// SqlBulkCopy'nin propertyleri
// Varsayilan veya yuksek degerlerle hic geri bildirim
// almayacaktik, o nedenle bu degerleri oldukca kucuk
// degerlere kuruyoruz.
sbc.NotifyAfter = 20;
sbc.BatchSize = 10;
//sbc.BulkCopyTimeout = 10000;
sbc.DestinationTableName = "##SqlBulkSample";
// Notify in between
// Arada notification
sbc.SqlRowsCopied += (sender,e) =>
{
Console.WriteLine("-- Copied {0} rows to {1}.",
e.RowsCopied,
((SqlBulkCopy)sender).DestinationTableName);
};
// Write to server
// server'a yaz
sbc.WriteToServer(rdr);
if (!rdr.IsClosed) { rdr.Close(); }
cn.Close();
// Check that it is really written to server.
// Just for testing the sample.
// Server'a hakikaten yazildigini kontrol ediyoruz.
// Bu sadece ornekte test icin.
SqlCommand cmdRead = new SqlCommand("select * from ##SqlBulkSample", scn);
tbl.Load(cmdRead.ExecuteReader());
scn.Close();
}
// Show the data read from SQL server
// Serverdan okunanlari bir formda goster.
Form f = new Form();
DataGridView dgv = new DataGridView();
dgv.Location = new Point(0, 0);
dgv.Dock = DockStyle.Fill;
dgv.DataSource = tbl;
f.Controls.Add(dgv);
f.ClientSize = new Size(1024, 768);
f.ShowDialog();
}
And also, your software might directly use the VFP data without getting it into MS SQL Server (I don't think you would want to do that but anyway).
HTH

SQL Server 2016 SSIS get cursor from stored procedure

I am using SQL Server 2016.
I have a stored procedure GET_RECORDS that takes input parameters for filter and outputs a CURSOR parameter
I want to get this cursor in my SSIS package
I had created data flow task, OleDb source and variables for parameter values. Then mapped parameters
Params mapping screen
but when I wanted to save the component - I got an error
error screen
I tried to add clause WITH RESULT SETS with some dummy columns, but my procedure doesn't return any result set
What am I doing wrong?
Any advices will be helpful.
Thank you.
With regards, Yuriy.
The source component is trying to determine what columns and types will be returned. Because you are using dynamic SQL the metadata can change each time you run it.
With result sets allows you to define the data being returned but should only be used if you are guaranteed to have those results every time you execute.
EDIT:
I create a connection and run the command so that it populates a data table. Then I put the column headers into a string array. There are plenty of examples out there.
Then I use the following function to create a destination table. Finally I create a datareader and pass that to the .Net SqlBulkCopy. Hope this helps.
private void CreateTable(string TableName, string[] Fields)
{
if (TableExists(TableName) && Overwrite)
{
SqlCommand = new SqlCommand($"Drop Table [{TableName}]", SqlConnection);
SqlCommand.ExecuteNonQuery();
}
string Sql = $"Create Table [{TableName}] (";
int ColumnNumber = 1;
foreach (string Field in Fields)
{
string FieldValue = Field;
if (! HasHeaders)
{
FieldValue = "Column" + ColumnNumber;
ColumnNumber++;
}
Sql += $"[{FieldValue}] Varchar(8000),";
}
Sql = Sql + "ImportFileID Int, ID Int Identity(1,1) Not Null, Constraint [PK_" + TableName + "] Primary Key Clustered ([ID] Asc))";
SqlCommand = new SqlCommand(Sql, SqlConnection);
SqlCommand.ExecuteNonQuery();
}
Use ado.net source instead of oledb source, define a simple select and get the columns you wish to return. Now you can define expresión in the dataflow properties.
Search ado.net source dynamic sql
:)
try to return the records and use foreach in ETL instead of cursor
https://www.simple-talk.com/sql/ssis/implementing-foreach-looping-logic-in-ssis/
I think you can do it from a simple way, but I don't know what you are you doing, exactly...

Copy table from one database to another in Windows Forms using C# and MS Access Oledb

How to copy a table from one database to another , I'm developing a windows app using c# in .NET.The copying has to be done by the app. Extract data into an empty table in database 2 from a filled table in database1.I'm using access db , Oledbconnection. I found some answers for sql server though , but not really helping.
You can refer to the second DB in SQL and execute against a connection to the first mdb/accdb:
Connection
using System.Data.OleDb;
<...>
string ConnString =
#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Z:\Docs\first.accdb";
OleDbConnection conn = new OleDbConnection(ConnString);
SQL
INSERT INTO Contacts ( ID, [A Text] ) IN 'z:\docs\New.accdb'
SELECT Contacts.ID, Contacts.[A Text]
FROM Contacts;
Or
INSERT INTO [;DATABASE=Z:\Docs\new.accdb].Contacts ( ID, [A Text] )
SELECT Contacts.ID, Contacts.[A Text]
FROM Contacts;
Or to create a table:
SELECT Contacts.ID, Contacts.[A Text] INTO Contacts IN 'z:\docs\New.accdb'
FROM Contacts;

C# 20,000 records selected from oracle need to be inserted into SQL2005

i have a console app in c# that extracts 20 fields from an oracle DB witht he code below and i wanted an efficient way to insert them into SQL 2005.
i dotn want to insert each one of the 20,000 within the while loop, obviously. i was thinking to change the code to use a data set to cache all the records and then do a bulk insert...
thoughts?
pseudo code would be nice since i am new to oracle.
this is my code where i was testing getting a connection to oracle and seeing if i can view the data... now i can view it i want to get it out and into sql2005... what do i do from here?
static void getData()
{
string connectionString = GetConnectionString();
using (OracleConnection connection = new OracleConnection())
{
connection.ConnectionString = connectionString;
connection.Open();
OracleCommand command = connection.CreateCommand();
string sql = "SELECT * FROM BUG";
command.CommandText = sql;
OracleDataReader reader = command.ExecuteReader();
while (reader.Read())
{
//string myField = (string)reader["Project"];
string myField = reader[0].ToString();
Console.WriteLine(myField);
}
}
}
You can create a CSV file and then use BULK INSERT to insert the file into SQL Server. Have a look here for an example.
The "bulk" insert with the cached Dataset will work exactly like the while loop you are not wanting to write! The problem is that you'll lose control of the process if you try to use the "bulk" insert of the Dataset class. It is extraneous work in the end.
Maybe the best solution is to use a DataWriter so that you have complete control and no Dataset overhead.
You can actually do 100-1000 inserts per sql batch. Just generate multiple inserts, then submit. Pregenerate the next SELECT batch WHILE THE FIRST EXECUTES.

How to add #temp tables

I have formed few temp tables in my query (TSQL) like - #temphold1, #temphold2, #temphold3..... #temphold10. Each temp table has different schema (different columns) each derived by grouping data from different tables with specific conditions. I need to determine a way to carry all these temp tables to the User Interface and display each table seperately. Is there a way I can add all temp tables with specific indexer that i can retrieve at the User Interface.
thanks for any reply.
No, there is no such indexer.
However, SQL Server and ADO.NET support returning multiple result sets by selecting each table in turn.
See this howto on MSDN (How To Handle Multiple Results by Using the DataReader in Visual C# .NET).
So, in your stored procedure:
-- after populating your temp tables:
SELECT * FROM #table1
SELECT * FROM #table2
SELECT * FROM #table3
In essence, after reading the first recordset, you call NextResult() on the DataReader in order to get the results of the next select:
while(dr.Read())
{
// process data from #table1
}
dr.NextResult();
while(dr.Read())
{
// process data from #table2
}
dr.NextResult();
while(dr.Read())
{
// process data from #table3
}
If you're returning results to C#, you can do it with a DataAdapter like this:
using (SqlConnection conn = new SqlConnection("your connection string")) {
SqlParameter[] sqlParams = new SqlParameter[] {
new SqlParameter("#param1",10),
new SqlParameter("#param2","test")
};
conn.Open();
SqlDataAdapter sa = new SqlDataAdapter("spStoredProcName", conn);
sa.SelectCommand.CommandType = CommandType.StoredProcedure;
sa.SelectCommand.Parameters.AddRange(sqlParams);
DataSet ds = new DataSet();
sa.Fill(ds);
//ds.Tables[0] == first table
//ds.Tables[1] == second table
//... etc.
//Do whatever you need to here
}

Resources