I would like to call the DB_ID function of SQL Server to retrieve the databaseID of a user database from scala..
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
val connection: Connection = DriverManager.getConnection(jdbcConnectionString)
//SELECT database_id FROM sys.databases WHERE Name
val statement: CallableStatement = connection.prepareCall("{? =call DB_ID(?)}")
statement.registerOutParameter(1,java.sql.Types.INTEGER)
statement.setString(2,s"'ABC_STORE'")
statement.execute()
val a = statement.getInt(1)
I get an error COULD NOT FIND the stored procedure DB_ID.
How do i get this to work.
If you make statement.setString you don't need to use your String between the two '' so change :
statement.setString(2,s"'ABC_STORE'")
by
statement.setString(2, "ABC_STORE")
What the s do in 2,s"' make sure to remove it.
You can learn more here :
Using a Stored Procedure with a Return Status and Prepared Statement doc
Related
I'm trying to use groovy.sql.Sql to create databases in an MSSQL (Microsoft SQL Server) server. It seem like the prepared statement adds additional quotes around the last parameter breaking the query.
This test code:
import groovy.sql.Sql
import com.microsoft.sqlserver.jdbc.SQLServerDataSource
def host = 'myhost'
def port = '1433'
def database = 'mydatabasename'
def usernameName = 'myusername'
def password = 'mypassword'
def dataSource = new SQLServerDataSource()
dataSource.setURL("jdbc:sqlserver://$host:$port")
dataSource.setUser(username)
dataSource.setPassword(password)
def connection new Sql(dataSource)
connection.execute(
'IF EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE name = ?) DROP DATABASE ?',
[ databaseName, databaseName ]
)
Gives the error:
Failed to execute: IF EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE name = ?) DROP DATABASE ? because: Incorrect syntax near '#P1'.
How can I use prepared statements without having it add single quotes around parameter one (DROP DATABASE ? seem to be rewritten as DROP DATABASE '?') or can I write the query in a different way so that the added single quotes does not produce a syntax error?
I would also be fine with other frameworks, if anyone could give me a working example.
Can you try:
connection.execute(
"IF EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE name = $databaseName) DROP DATABASE ${Sql.expand(databseName)}"
)
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...
I am trying to use GO to get R to pull a multipart query from a SQL Server database but R keeps erroring out on me when I try this. Does anyone know a workaround to get RODBC to run multipart queries?
Example query:
query2 = "IF OBJECT_ID('tempdb..#ATTTempTable') IS NOT NULL
DROP TABLE #ATTTempTable
GO
SELECT
* INTO #ATTTempTable
FROM ETL.ATT.fact_responses fr
WHERE fr.ResponseDateTime > '2015-07-06'
"
channel <- odbcConnect("<host name>", uid="<uid>", pwd="<pwd>")
raw = sqlQuery(channel, query2)
close(channel)
and result
> raw
[1] "42000 102 [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Incorrect syntax near 'GO'."
[2] "[RODBC] ERROR: Could not SQLExecDirect 'IF OBJECT_ID('tempdb..#ATTTempTable') IS NOT NULL\n DROP TABLE #ATTTempTable\n\nGO\n\nSELECT\n\t* INTO #ATTTempTable\nFROM ETL.ATT.fact_responses fr\nWHERE fr.ResponseDateTime > '2015-07-06'\n'"
>
Because your query contains multiple line with conditional logic it resembles a stored procedure.
Simply save that stored procedure in SQL Server:
CREATE PROCEDURE sqlServerSp #ResponseDateTime nvarchar(10)
AS
IF OBJECT_ID('tempdb..#ATTTempTable') IS NOT NULL
DROP TABLE #ATTTempTable;
GO
-- suppresses affected rows message so RODBC returns a dataset
SET NO COUNT ON;
GO
-- runs make-table action query
SELECT * INTO #ATTTempTable
FROM ETL.ATT.fact_responses fr
WHERE fr.ResponseDateTime > #ResponseDateTime;
GO
And then run the stored procedure in R. You can even pass parameters like the date:
channel <- odbcConnect("<host name>", uid="<uid>", pwd="<pwd>")
raw = sqlQuery(channel, "EXEC sqlServerSp #ResponseDateTime='2015-07-06'")
close(channel)
You can't. See https://msdn.microsoft.com/en-us/library/ms188037.aspx
you have to divide your query into two statements and run them separately.
Suppose I generate the PK for my SQL Server DB table with the help of newid() function. In Java I can do something like this:
...
String query = "DECLARE #newGuid uniqueidentifier "+
"SET #newGuid = newid() "+
"INSERT INTO myTable(id, stringval) "+
"VALUES (#newGuid, "Hello") "+
"SELECT uid FROM #newGuid";
PreparedStatement ps = conn.prepareStatement(query);
ResultSet rs = ps.executeQuery();
String uid = rs.getString("uid");
But when I try to make that with Delphi+ADO I get stuck cause ADO can either get data from DB (Open method of AdoQuery) or put data to DB (ExecSQL method). So I can't insert new value to the table and get the parameter value afterwards.
You could solve this problem atleast in two ways.
You can put both of your SQL queries into one string (just like you have in your example) and call TADOQuery.Open or TADOQuery.Active := True. it doesn't matter that you have INSERT statement there as long as query returns something.
You can define parameter's direction as pdOutput in ADOQuery.Parameters collection and read value of that parameter after executing the query.
You are treating #newGuid as if it was a table. Your last row in the query should be:
SELECT #newGuid as uid
In the JDBC code, I have the following that is working with SQL Server:
CallableStatement stmt = connection.prepareCall("{ call getName() }");
ResultSet rs = stmt.executeQuery();
if(rs != null)
{
while(rs.next())
{
//do something with rs.getString("name")
}
}
Multiple rows are returned for the above situation.
I understand that the use of a cursor is required to loop through the table in Oracle, but is there any way to keep the above code the same and accomplish the same thing?
Sample PL/SQL code would be much appreciated.
Thanks in advance.
You could implement getName() as a pipelined function:
CREATE OR REPLACE name_record AS OBJECT ( name VARCHAR2(100) );
/
CREATE OR REPLACE name_table AS TABLE OF name_record;
/
CREATE OR REPLACE FUNCTION getName RETURN name_table PIPELINED
AS
n name_record;
BEGIN
-- I have no idea what you're doing here to generate your list of names, so
-- I'll pretend it's a simple query
FOR i IN (SELECT name FROM someTable) LOOP
n := name_record( i.name );
PIPE ROW(n);
END LOOP;
END;
/
You would need to change the actual query in Java to SELECT name FROM TABLE(getName()).
This is straight JDBC, so it'll work with any database that has a valid JDBC driver.
It assumes, of course, that the stored proc exists in both and that you aren't using any non-standard, vendor-proprietary code in your class.