I got an error:
Must declare scalar variable '#20'
...when loading a webpage to fetch query data.
I've done a few web inquiries but i don't understand why a variable needs to be declared.
This started, when I had written out the code and loaded the page, it worked fine. Made a few modifications to unrelated parts of the page, refreshed again and started getting an error. I've never had to deal with declare before.
var db = Database.Open("StarterSite");
var selectQueryString = "SELECT * FROM business_Customer WHERE memberid=#20";
var memberid = Database.Open("StarterSite").QueryValue("SELECT memberid FROM business_Customer WHERE email=#0",WebSecurity.CurrentUserName);
That's the script at the top of my page, right before the html loads.
foreach (var row in db.Query(selectQueryString, memberid)) {...}
...is the script that is giving me the error.
But before modifying and adding to the page, the memberid variable worked just fine. The value is an integer, and i used it separately, by itself to confirm that it works. I tried changing the snippet to foreach (var row in db.Query(selectQueryString, (int) memberid)) {...} and it gave me an error that said:
Cannot convert null to 'int' because it is a non-nullable value type
I'm extremely confused... What does declaring have to do with calling a value from an sql database? Is there a simple solution to my problem? i read other stackoverflow posts related to this, but the solutions were written in SQL syntax, and used "Declare", there wasnt enough resources for me to understand how to apply their solution to my problem.
I discovered what was wrong with my script. It was missing an external javascript file, needed for another set of values, that somehow had something to do with error. But... my original for my original question, is declaring a variable something i need to know? I dont mind studying it (if there were resources that went into details on what it's for, or when it's used), but i've never had to deal with it before... is it something "important/valuable"?
You should be using #0 - this represents the first argument.
Query and QueryValue both take 2 parameters - a commandText and an array of parameters. To specify where the parameters go in your commandtext, you use #0, #1, etc.
For example:
var selectQueryString = "SELECT * FROM business_Customer WHERE memberid=#0";
db.Query(selectQueryString, memberid)
So when you call Query, it will replace #0 with the value of the memberid variable.
Related
I am attempting to use ExecuteSqlInterpolated to update my database. However, it seems that there is a problem with my SQL parameters. Running the following code correctly updates intField1 and intField2, however stringField becomes the string "#p0".
_context.Database.ExecuteSqlInterpolated($"UPDATE table SET stringField='{someString}', intField1={someInt}, intField2={someOtherInt} WHERE id='{id}'");
I have already verified that my variables contain the desired values when the string is passed to the method. I understand that #p0 is what SQL uses to represent the first parameter in the query, but why isn't it being replaced by the string I gave it? I have also tried using ExecuteSqlRaw but ran into the same issue. My knowledge of SQL is limited at best, I know just enough to get by in web dev, so I'm guessing I'm committing some simple error in crafting the query here, but obviously I'm not sure.
I know it's late but just don't use quotation mark with your parameters, specially where you use int data-type
(delete single quotes)
_context.Database.ExecuteSqlInterpolated($"UPDATE table SET stringField={someString}, intField1={someInt}, intField2={someOtherInt} WHERE id={id}");
I am currently receiving an error when trying to execute a simple SELECT statement that references an assembly that contains the C# code for the Jaro-Winkler distance algorithm. This is my first time working with SQLCLRs.
I am able to run the code successfully below without the additional OR statement
Example:
SELECT
*
FROM
USERS
WHERE
(
DATE_OF_BIRTH IS NOT NULL
AND DBO.JAROWINKLER(CONVERT(VARCHAR(6),DATE_OF_BIRTH,12),#DOB) > 0.9
)
OR
(
USERID = #USERID
)
However when I include the OR statement I receive this error message:
A .NET Framework error occurred during execution of user-defined routine or aggregate "JaroWinkler":
System.NullReferenceException: Object reference not set to an instance of an object.
System.NullReferenceException:
at JaroWinklerDistanceCLR.JaroWinklerDistance.proximity(String aString1, String aString2)
The code below works and does what is needed. I just wondered if there was another way? Ideally, I would like it contained to one SELECT statement. I have no idea what the error above is referring to, there are no NULL values in the UserID column.
The permission set for the assembly is set to Safe.
Working example:
SELECT
*
FROM
USERS
WHERE
DATE_OF_BIRTH IS NOT NULL
AND DBO.JAROWINKLER(CONVERT(VARCHAR(6),DATE_OF_BIRTH,12),#DOB) > 0.9
UNION ALL
SELECT
*
FROM
USERS
WHERE
USERID = #USERID
The other two answers are work arounds, not solutions. And this work-around will have to be duplicated in every place where this function is used, and that is very error-prone and difficult to maintain.
Before getting into the main problem here, there is a minor, related problem that should be fixed first: the input parameter types are incorrect. For SQLCLR methods, you should use the Sql* types instead of the standard .NET types. For this particular code, that means using SqlString instead of String. For more details on why SqlString instead of String, please see my answer to the following S.O. question: Should I use SqlString or string as parameter type to SQLCLR UDF's.
Now, the problem is that the SQLCLR code is not properly handling NULLs. Fortunately, it is not difficult to get it to handle them. There are two options, depending on if any of the input parameters can accept a NULL or not:
If any of the input parameters can validly pass in a NULL, then you need to handle this in the code (and this also applies to all cases when working with Table-Valued Functions and Stored Procedures). And you check in the code via the .IsNull property that all of the Sql* types have. For example (assuming aString2 can pass in a NULL):
if (aString1.IsNull)
{
return SqlDouble.Null;
}
If none of the input parameters can validly accept NULL, then you should bypass all processing without entering the code in the first place by creating the Scalar UDF with the WITH RETURNS NULL ON NULL INPUT option of the CREATE FUNCTION statement. With this option set, if any input parameter is NULL, then the code is skipped and a NULL return value is assumed. Please note that this only works with Scalar UDFs and User-Defined Type methods.
For more information on working with SQLCLR in general, please see the series of articles I am writing on this topic on SQL Server Central (free registration is required to read content on that site): Stairway to SQLCLR.
On a related note, I would question the use of a string distance function to do what is a rather simple date calculation. I would think that this code would benefit greatly from replacing the JaroWinkler function with a DATEDIFF based on converting the string #DOB to DATE or DATETIME.
The OR statement is most likely including NULL values into your result set which are returning as a different data type. Try using
OR (USERID = #USERID AND AND P.DATE_OF_BIRTH IS NOT NULL)
or, if you require the NULL values then select the field names explicitly (rather than select *) and wrap the date_of_birth field in a convert statement
Thank you. NULL values in the date of birth field.
Working!
SELECT
*
FROM
USERS
WHERE
(
DBO.JAROWINKLER(CONVERT(VARCHAR(6),ISNULL(P.DATE_OF_BIRTH,''),12),#DOB) > 0.9
)
OR
(
USERID = #USERID
)
so there are a few other similar type posts about, but none matching the simple task I am attempting.
just running a stored proc through EF6 code first in the following manner
var results = context.DataBase.SqlQuery<MyClass>("exec spGetStuff #param1, #param2", new SqlParameter[] {new SqlParameter("param1",value), new SqlParameter("param2", value2)});
I have used this method on many occasions with no issue.
the class I am mapping the results to is pretty nasty with many properties, but all that need it are marked with the [Column("dbfieldname")] attribute.
all the stored proc is doing is returning some results by using a
SELECT * FROM(
SELECT
ROW_NUMBER() OVER ( PARTITION BY X,Y,Z ORDER BY A) [RowNumber]
,*
FROM
MyTableNAme
WHERE
...) S
WHERE s.RowNumber = 1
not inserting, updating or anything fantastical like that.
The data reader is incompatible with the specified 'MyClass'. A member of the type, 'PropertyNameName', does not have a corresponding column in the data reader with the same name.
if I do change the class properties to the db column names it seems to work fine:I can change the first few properties and it will then fail on other ones in the class... however I do not really want to do that if I can possibly avoid it as most of the columns in the DB are named very badly indeed, so I guess my question is why is it ignoring the [Column()] attributes that have never failed me before.
or is the issue the row_number, which I have tried adding to the class an/or removing from the query resultsset.
We're seeing this issue too since upgrading and refactoring for EF6 from 5. Stored procedure returns and we have a Complex Type defined in our edmx. It seems that everything matches up but we get the same type of error when calling like this
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<GetColumnValueSet_Result>("GetColumnValueSet", param1, param2, param3);
So after trying a few things this is what I found. I opened my edmx and went to the Model Browser within Visual Studio. Under Function Imports I found my sproc. Right clicked and chose Function Import Mapping. It turned out that even though the complex type was correct and it appeared everything should have matched up the Function Import Mapping was thinking the sproc was returning a column called CodeValue instead of Value (which is what it was actually importing).
So for some reason when the sproc columns were gotten it go a wrong name for the mapping.
I am trying to use ALTER USER query for Oracle database using OracleCommand in C# in the following code. It creates the query if the values for Username and password are not empty strings. But I get an error "ORA-01036: illegal variable name/number" when ExecuteNonQuery() is executed.
string updateQuery = "ALTER USER :user IDENTIFIED BY :password";
connection = new OracleConnection(LoginPage.connectionString);
connection.Open();
OracleCommand cmd = new OracleCommand(updateQuery, connection);
cmd.Connection = connection;
for(int i=0;i<usersList.Count;i++)
{
if (!(selectedUsersArray[i].Equals("")) && !passwordArray[i].Equals(""))
{
OracleParameter userName = new OracleParameter();
userName.ParameterName = "user";
userName.Value = selectedUsersArray[i];
OracleParameter passwd = new OracleParameter();
passwd.ParameterName = "password";
passwd.Value = passwordArray[i];
cmd.Parameters.Add(userName);
cmd.Parameters.Add(passwd);
cmd.Prepare();
cmd.ExecuteNonQuery();
}
}
Could you please suggest what is wrong with my implementation?.
The root cause
In Oracle you have three kinds of SQL statements (and additionally there are PL/SQL blocks):
Statements in the Data Definiton Language (DDL). These statements modify the structure of the database. They begin usually with the verbs "ALTER" or "CREATE"
Statements in the Data Modification Langugage (DML). There statements modify the content inside of tables, leaving the structure of each table unmodified. These statements usually begin with "INSERT", "MERGE" or "DELETE".
Statements in what I call "query language" (there seems to be no canonical name for these). This statements start with the verb "SELECT".
Bind variables in Oracle are only allowed in some special places in DML and query statements. You are trying to use bind variables in a places where they are not allowed. Hence the error.
Solution
Build your statement without bind variables. Build the complete query string instead using string concatenation.
If you want to sanitize the input before concatenating the string, use the DBMS_ASSERT package.
Background
Bind variables can only be used when Oracle can build a query plan without knowing the value of the variable. For DDL statements, there is no query plan. Hence bind variables are not allowed.
In DML and query statements, bind variables are only allowed, when they are used inside a tuple (regarding the underlying set theory), i.e. when the value will be compared with the value in a table or when the value will be inserted in a table. They are not allowed to change the structure of the execution plan (e.g. to change the target table or to change the number of comparisons).
Just for others getting this error and looking for info on it, it is also thrown if you happen to pass a binding parameter and then never use it. I couldn't really find that stated clearly anywhere but had to prove it through trial and error.
I just spent several days checking parameters because I have to pass 60 to a stored procedure. It turns out that the one of the variable names (which I load into a list and pass to the Oracle Write method I created) had a space in the name at the end. When comparing to the variables in the stored procedure they were the same, but in the editor I used to compare them, I didnt notice the extra space. Drove me crazy for the last 4 days trying everything I could find, and changing even the .net Oracle driver. Just wanted to throw that out here so it can help someone else. We tend to concentrate on the characters and ignore the spaces. . .
You defined one oracleCommand but used it in 'for'.
it means you are adding parameter with the same name to one OracleCommand.
you should use cmd.Parameters.clear() to refresh your parameters.
for(int i=0;i<usersList.Count;i++)
{
if (!(selectedUsersArray[i].Equals("")) && !passwordArray[i].Equals(""))
{
cmd.Parameters.clear();//Add this line
OracleParameter userName = new OracleParameter();
userName.ParameterName = "user";
userName.Value = selectedUsersArray[i];
OracleParameter passwd = new OracleParameter();
passwd.ParameterName = "password";
passwd.Value = passwordArray[i];
cmd.Parameters.Add(userName);
cmd.Parameters.Add(passwd);
cmd.Prepare();
cmd.ExecuteNonQuery();
}
}
The Oracle error ORA-01036 means that the query uses an undefined variable somewhere. From the query we can determine which variables are in use, namely all that start with #. However, if you're inputting this into an advanced query, it's important to confirm that all variables have a matching input parameter, including the same case as in the variable name, if your Oracle database is Case Sensitive.
This error happens when you are also missing cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add(new OracleParameter("GUSERID ", OracleType.VarChar)).Value = userId;
I was having eight parameters and one was with space at the end as shown in the above code for "GUSERID ".Removed the space and everything started working .
I was having the same problem in an application that I was maintaining, among all the adjustments to prepare the environment, I also spent almost an hour banging my head with this error "ORA-01036: illegal variable name / number" until I found out that the application connection was pointed to an outdated database, so the application passed two more parameters to the outdated database procedure causing the error.
You cannot pass user/table name to pl/sql with a parameter. You can create a procedure and build sql and then execute immediately to achieve that.
I have faced same problem ... For the problem is like this, I am calling the PRC inside cpp program and my PRC taking 4 arguments but while calling I used only 1 arguments so this error came for me.
Begin Example_PRC(:1); End; // this cause the problem
Begin Example_PRC(:1,:2,:3,:4); End; // this is the solution
I had the same issue today when using Python module cx_Oracle. In my case, the root cause was an invalid variable name.
Example: SELECT * FROM DATA WHERE KEY IN (:_0, :_1, ...)
When I changed _0 to var0, it worked fine.
From this blog post, I found these rules for variable names:
Must start with a letter
Maximum size is limited to 30 letters
Cannot contain whitespace characters
Can contain dollar sign ('$'), underscore ('_') and hash sign ('#')
Is case-insensitive
I had the same problem, was learning connection to oracledb.
previous code-
SELECTALLCANDIDATES = "Select * from candidate_master";
data= await connection.execute(SELECTALLCANDIDATES, {autoCommit:true})
Removed the {autoCommit:true} and it started working fine.Correct code-
SELECTALLCANDIDATES = "Select * from candidate_master";
data= await connection.execute(SELECTALLCANDIDATES)
Still don't know why but it works.
Check your named variables match, I had the same problem, I had a spelling mistake/typo in one of my parameters
Part of our solution is a page that displays company-specific information using an ASP Gridview. Our method of constructing the SQL that feeds the Gridview is by using C# to build a custom SELECT statement based on a series of user inputs.
Once the user applies their filters through a button click, C# loops through all of their selections (check boxes and text boxes) and then propagates those selections to a separate method which constructs a WHERE clause to append to a simple SELECT statement. We use a Table-Valued Function in the FROM statement, and the only input parameter is from the Querystring and this does not change throughout the process.
Once the query has been assembled using C#, we apply this query to the SqlDataSource as the Select Command. However, we have recently discovered a very bizarre SQL error that we haven’t seen before:
Errors :
"The variable name '#' has already been declared.
Variable names must be unique within a query batch or stored procedure."
We aren’t declaring any variables in our SQL. As stated above, the only input parameter comes from the Querystring, and we access this parameter using both QueryStringParameters in the ASP:SqlDataSource on the ASP side and “int.Parse(Request.QueryString["id"]).ToString()” on the C# side while constructing the SQL query.
After researching this error, I have yet to find an instance where the variable declaration is empty. Most people are getting errors similar to this when they have declared a variable such as '#email' or '#address' twice. We have no double declarations, and the fact that the variable in the error is not defined is causing a massive headache.
Has anyone seen anything like this before or have any suggestions on how to further debug?
I'll post some code if need be, but we are mostly interested to see if anyone has seen an error like this before.
Code:
string MainQueryStr = ResultsPages.SearchString(SearchVariables(), Request,
ProjectsSqlds, 0, "SELECT DISTINCT dbo.{0}.* FROM dbo.{0}(" + int.Parse(Request.QueryString["id"]).ToString() + ")",
"getXyzById", "AbcId");
StringBuilder SearchQueryStr = new StringBuilder();
SearchQueryStr.Append(MainQueryStr);
SearchQueryStr.Append(" ORDER BY AbcName");
ProjectsSqlds.SelectCommand = SearchQueryStr.ToString();
The search string function is a 500 line method that we can't post right now. It is used all over our solution and works as it should. It stitches together strings to create the query.
This is how the SearchString function appends the parameters:
l.Add(ResultsPages.NewSearchQueryString(ABCFiltersTxBx, SearchQueryStringVariableType.String,
"{1}.AbcID IN (" + ABCFiltersTxBx.Text + ")"));
Where the ABCFiltersTxBx is parsed into a comma separated string.
I should chime in as the supervisor in question here:
OK, so we figured out what was happening.
What we didn't realize was that the SQLDataSource was taking our appended WHERE clauses and using them as SelectParameters. Each parameter we wanted to add to the query that would ultimately feed the SQLDS was then being added as a SelectParameter without us realizing it, and because we hadn't made any explicit parameter declarations, the parameters were added with just "" as the name, leading to the error of "'#' has already been declared".
The most embarrassing part of this whole thing is that our API has already accounted for Parameter Names, but we had unwittingly excluded this part. Thank you all very much for reading and attempting to help. We thoroughly appreciate you taking your time to help us brainstorm our solution over here.
So I suppose the take-home of this whole error is in 2 parts:
Know your API. When you realize that you screwed it up on your own, graciously thank those that took the time to help you here on StackOverflow (or wherever you seek help), as their time is valuable as well.
"'#' is already declared" would indicate that you have parameters being declared without a name, so when debugging, look through the SQLDS you are using and find any parameters that haven't been explicitly named.
Again, thank you to all who read and offered to help. It's greatly appreciated.