Problems deleting data from database - database

I am using Hibernate to access my database. I would like to delete a set of fields on function of a criteria. My database is PostgreSQL and my Java code is:
public void deleteAttr(String parameter){
Configuration cfg = new Configuration();
cfg.configure(resource.getString("hibernate_config_file"));
SessionFactory sessionFactory = cfg.buildSessionFactory();
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
tx.begin();
String sql = "delete from attribute where timestamp > to_date('"+parameter+"','YYYY-MM-DD')"
session.createSQLQuery(sql);
tx.commit();
}
The method runs, but it doesn't delete data from database. I have also checked the sql sentence in PgAdmin and it works, but not in code. Why? Does someone help me?
Thanks in advance!

It's because you're creating a query, but you don't execute it:
String sql = "delete from attribute where timestamp > to_date('"+parameter+"','YYYY-MM-DD')"
Query query = session.createSQLQuery(sql);
query.executeUpdate();
You should really use bound named parameters rather than string concatenation to pass parameters in your query: it's usually more efficient, it' much more robust, but above all, it doesn't open the door to SQL injection attacks.

Related

How to execute stored procedure on ODBC Snowflake Destinastion?

I'am building new package for move data from aws sql server instance to snowflake odbc destination. If i found rows which was updated i must change them on snowflake as well. In common's i found only 'OLE DB Command' for execute procedure for update diffrent rows.
The problem is i need something like "ODBC Command" for execute procedure to update diffrent rows between SQL Server&Snowflake.
OK, I do it.
So if u need UPDATE rows on ODBC destination in SSIS u have only one way to do that u need to use Script Component. Before I thought it will be something like ODBC Command and we will need to write stored procedure to change rows in the destination. I link that for ppl who care in the future.
The OLE DB Command transformation runs an SQL statement for each row in a data flow. For example, you can run an SQL statement that inserts, updates, or deletes rows in a database table.
Microsoft OLE DB Command description
I wrote a simple code in c# to Update Rows and it works perfectly. U can simple rebuild it for execute procedure or do whatever u need.
public class ScriptMain : UserComponent
{
OdbcConnection odbcConn;
OdbcCommand odbcCmd;
OdbcParameter odbcParam;
public override void AcquireConnections(object Transaction)
{
/// Create a String base on that which u define on package for connection and
adding a password
string connectionString;
connectionString = this.Connections.SFConnection.ConnectionString;
odbcConn = new OdbcConnection(connectionString + "PWD=YOURPASSWORD");
odbcConn.Open();
}
public override void PreExecute()
{
///Create command which we wanna execute
base.PreExecute();
odbcCmd = new OdbcCommand("UPDATE klienci SET IMIE= ?,NAZWISKO= ? ,NUMER_TELEFONU= ? ,EMAIL= ? ,ULICA= ? ,MIASTO= ? ,STATE= ? ,ZIP_CODE = ? WHERE CUSTOMER_ID= ?", odbcConn);
}
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
///Adding parameters and connecting them with our input column from package
odbcCmd.Parameters.AddWithValue("#IMIE", Row.Sourcefirstname);
odbcCmd.Parameters.AddWithValue("#NAZWISKO", Row.Sourcelastname);
odbcCmd.Parameters.AddWithValue("#NUMER_TELEFONU", Row.Sourcephone);
odbcCmd.Parameters.AddWithValue("#EMAIL", Row.Sourceemail);
odbcCmd.Parameters.AddWithValue("#ULICA", Row.Sourcestreet);
odbcCmd.Parameters.AddWithValue("#MIASTO", Row.Sourcecity);
odbcCmd.Parameters.AddWithValue("#STATE", Row.Sourcestate);
odbcCmd.Parameters.AddWithValue("#ZIP_CODE", Row.Sourcezipcode);
odbcCmd.Parameters.AddWithValue("#CUSTOMER_ID", Row.Sourcecustomerid);
odbcCmd.ExecuteNonQuery();
}
}

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...

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.

Is there an alternative of using a VBScript for enabling FileStream after SQL Server installation?

To use Filestream on a DB 3 steps must be done:
1) enable it a server/instance level
2) enable it (sp_configure) at DB level
3) create a varbinary(max) field that supports filestream
(2) and (3) are done easily with T-SQL
(1) is doable manually from SQL Server Configuration Manager, basically what I need is to check all the 3 checkboxes:
(source: sql-server-performance.com)
but how is it possible to automize it?
I found this artcile "Enabling filestream usin a VBScript", is there another way to do it than using VBScripts? May be something that is possible to do only with 2008R2?
In case it VBScript is the only solution, which are the possible downsides?
The only way other than clicking in the Configuration Manager is via WMI (which is what the VBScript does). If you don't like VB, here's how I've been configuring it from C# (note that the code needs to run with admin privileges (elevated)):
private ManagementObject GetFilestreamManagementObject(string machineName, string instanceName)
{
string managementPath = string.Format(#"\\{0}\root\Microsoft\SqlServer\ComputerManagement10", machineName);
ManagementScope managementScope = new ManagementScope(managementPath);
managementScope.Connect();
SelectQuery query = new SelectQuery("FilestreamSettings", string.Format("InstanceName='{0}'", instanceName));
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(managementScope, query))
{
ManagementObjectCollection moc = searcher.Get();
if (1 != moc.Count)
{
string exceptionText = String.Format("Expected single instance of FilestreamSettings WMI object, found {0}.", moc.Count);
throw new FilestreamConfigurationException(exceptionText);
}
ManagementObjectCollection.ManagementObjectEnumerator enumerator = moc.GetEnumerator();
if (false == enumerator.MoveNext())
{
throw new FilestreamConfigurationException("Couldn't move ManagementObjectEnumerator to the first entry.");
}
return (ManagementObject)enumerator.Current;
}
}
private void EnableFilestream(int accessLevel)
{
ManagementObject filestreamSettingsObject = GetFilestreamManagementObject("myMachine", "MSSQLSERVER");
ManagementBaseObject methodArgs = filestreamSettingsObject.GetMethodParameters("EnableFilestream");
methodArgs["AccessLevel"] = accessLevel;
methodArgs["ShareName"] = ""; //default
ManagementBaseObject returnObject = filestreamSettingsObject.InvokeMethod("EnableFilestream", methodArgs, null);
if (returnObject == null)
{
throw new FilestreamConfigurationException("Result of calling filestreamSettingsObject.InvokeMethod(\"EnableFilestream\", methodArgs, null)" is null);
}
uint returnValue = (uint)returnObject.GetPropertyValue("ReturnValue");
const uint errorSuccessRestartRequired = 0x80070BC3;
if (returnValue != 0 && returnValue != errorSuccessRestartRequired)
{
Win32Exception win32Exception = new Win32Exception((int)returnValue);
string exceptionText =
string.Format("'EnableFilestream' method returned {0}: {1}", returnValue, win32Exception.Message);
throw new FilestreamConfigurationException(exceptionText);
}
}
Just run this.
USE master
Go
EXEC sp_configure 'show advanced options'
GO
EXEC sp_configure filestream_access_level, 3
GO
EXEC sp_filestream_configure
#enable_level = 3
, #share_name = N'FS';
GO
RECONFIGURE WITH OVERRIDE
GO
More on this
http://www.mssqltips.com/tip.asp?tip=1489
0 = disabled (this is the default)
1 = enabled only for T-SQL access
2 = enabled for T-SQL access and local
file system access
3 = enabled for T-SQL access, local
file system access, and remote file
system access
You can store the script in a stored procedure and call it from your application or anywhere you want.
Here're links on this topic
http://www.mssqltips.com/tip.asp?tip=1838
Link
http://technet.microsoft.com/en-us/library/cc645923.aspx
http://www.sql-server-performance.com/articles/dba/Configure_Filestream_in_SQL_Server_2008_p1.aspx
EDIT
Answer to your comment.
Here's what I call step 2
CREATE DATABASE Archive
ON
PRIMARY ( NAME = Arch1,
FILENAME = 'c:\data\archdat1.mdf'),
FILEGROUP FileStreamGroup1 CONTAINS FILESTREAM( NAME = Arch3,
FILENAME = 'c:\data\filestream1')
LOG ON ( NAME = Archlog1,
FILENAME = 'c:\data\archlog1.ldf')
GO
http://technet.microsoft.com/en-us/library/cc645585.aspx
Check link for all steps
Filestream in Sql Server 2008 Express
Good Luck!
Pawel's solution worked great for us. We were seeing about a 50% failure rate using the VBS -- haven't seen a failure yet with Pawel's approach. Unlike Greg's results, it has worked great for us against a local system. Actually, that's all we have tried it with.
We did have to make a couple of adjustments to Pawel's code. The line
throw new FilestreamConfigurationException("Result of calling filestreamSettingsObject.InvokeMethod(\"EnableFilestream\", methodArgs, null)" is null);
has the final quote character out of place. It should be after the "is null", right before the ");".
We also had to make sure we got the instanceName built correctly. For example, if we had "mymachine\myinstance", we had to make sure that "instanceName=myinstance" and not the full name. Further, if we had "mymachine" (the default instance), we had to have "instanceName=MSSQLSERVER". Maybe that is Greg's problem -- when we had the instanceName set to the wrong thing, we got the same results Greg reports.

How can I copy data records between two instances of an SQLServer database

I need to programmatically (ADO.Net) copy records from a table in one database to a table in another database on a different server.
This is very similar to "How can I copy data records between two instances of an SQLServer database" except that I am not allowed to create a link to the destination server so the accepted answer to that question won't work for me.
You can use the SqlBulkCopy class
The SqlBulkCopy class suggested by santiiii is very efficient but it creates a non-logged operation. I had to do this once but my target database participated in replication, so I needed the operation to be fully logged. What I essentially ended up doing was selecting a dataset from the source database .
Select * from SourceDatabaseTable where (some clause to get the right records)
Then creating an empty dataset from the destination table with this statement
Select * from DestinationDatabaseTable where 1<>1
Then I had two datasets. The first with the records I wanted to copy and the second that is empty. Next I just did a nested foreach loop to copy the records from one dataset to the other. Here is the Pseudocode for the core copy function:
foreach(datarow sourcedr in sourcetable)
{
datarow destdr = destdatatable.createrow();
foreach(datacolumn in sourcedatatable)
{
destdr[datacolumn]=Sourcedr[datacolum];
}
}
Lastly, I just used a data adapter to submit the changes on the destination database.
Here's how I did it. Thanks to the other respondants for the inspiration. The code that builds the mappings is not necessary if the schemas of the two tables are identical.
public void CopyTables(string sourceConnectionString, string destConnectionString)
{
string sql = "Select * From SourceTable";
using (SqlConnection sourceConn = new SqlConnection(sourceConnectionString))
using (SqlCommand sourceCmd = new SqlCommand(sql, sourceConn)) {
sourceConn.Open();
using (SqlDataReader reader = sourceCmd.ExecuteReader())
using (SqlBulkCopy copier = new SqlBulkCopy(destConnectionString)) {
copier.DestinationTableName = "DestinationTable";
copier.BulkCopyTimeout = 300;
DataTable schema = reader.GetSchemaTable();
copier.ColumnMappings.Clear();
foreach (DataRow row in schema.Rows) {
copier.ColumnMappings.Add(row["ColumnName"].ToString(), row["ColumnName"].ToString());
}
copier.WriteToServer(reader);
}
}
}
}

Resources