SqlDataAdapter and Computed Columns; not maintained? - sql

Let's say I have following SQL schema:
SQL
TABLE Person COLUMNS
(
ID AS INTEGER,
Firstname AS varchar(100),
Lastname AS varchar(100),
Fullname AS (Firstname + ' ' + Lastname)
)
GO
INSERT INTO Person (ID, Firstname, Lastname) VALUES (1, 'Simon', 'Dugré')
GO
VB retreiving class
Dim da as new SqlDataAdapter("SELECT ID, Firstname, Lastname, FullName FROM Person WHERE ID = 1", cn)
Dim ds as new DataSet()
da.Fill(ds)
da.FilleSchema(ds) ' I tried this before or after da.fill, just in case '
Dim dr as DataRow = ds.table(0).row(0)
Assert.IsTrue(dr("Firstname") = "Simon") ' Returns true '
Assert.IsTrue(dr("Lastname") = "Dugré") ' Returns true '
Assert.IsTrue(dr("Fullname") = "Simon Dugré") ' Returns true '
dr("Firstname") = "Nomis"
Assert.IsTrue(dr("Fullname") = "Nomis Dugré") ' Return False, it is still "Simon Dugré" in it. '
While debugging in the immediate window, I see the following:
?dr.table.Columns("Fullname").Computed ' It says it is set to false... Duhhh... no!'
More informations
I saw at a few places that there is a way to "hardcode" computed column formula directly from code by referring to the property instead of SQL fields... But I can't do that because to keep this question readable, I removed a lot of code but this is in fact part of a whole abstract and generic scenario.
My question is, is there in fact a way to have formula retrieved directly from SQL while calling da.Fill or da.FillSchema or something? Then, when changing Firstname or Lastname, it will automatically have an effect on the Fullname computed column?

It's not computed in the DataTable. That has no relation to how the column is defined in the database :)
There's no direct translation between SQL expressions and IL, so you'll have to type that in yourself manually, and maintain it as needed.
Of course, if you're only dealing with simple expressions, it's pretty easy to translate them automatically, you'll just have to write a parser. For stuff like this it's not even all that hard.

Related

Pass parameters by name to BigQuery stored procedure or function

In BigQuery we usually pass parameters to stored procedures and functions by position something like this:
CREATE TEMP FUNCTION FullName(firstName STRING, lastName STRING)
RETURNS STRING
AS(
firstName || ' ' || lastName
);
SELECT FullName("Fred", "Flintstone")
I would like to be able to not care about the position of the parameters when calling the function or stored procedure. Perhaps with something like this:
# This does not work
SELECT FullName("Flintstone" AS lastName, "Fred" AS firstName)
Unfortunately, this results in a syntax error. I have also tried a few other possibilities such as FullName(lastname="Flintstone", firstName="Fred"), etc and tried to search in the docs but came up blank.
Is there a mechanism for passing parameters by name in an arbitrary order like this?
You were very close (I think) - Use below
CREATE TEMP FUNCTION FullName(name ANY TYPE)
RETURNS STRING
AS(
name.firstName || ' ' || name.lastName
);
SELECT
FullName(STRUCT("Fred" AS firstName, "Flintstone" AS lastName)),
FullName(STRUCT("Flintstone" AS lastName, "Fred" AS firstName))
with output

How to search a full name in sql server database table with only firstname and lastname column?

We have a DB table, User with first_name, last_name columns but do not have a full_name column. We want to perform a search on the table, where the search query can contain the string which is a combination of both columns or one of them or simply a character. Search has to case insensitive.
Edit 1
The search needs to be fast enough as the request would be from a typeahead on a webclient.
The LIKE expressions by default are case insensitive. As #larnu suggested, adding a persistent column is a better way of going about it. And if you can do a prefix search on that, it will further speed things up. If those are not an option, try this to see if you can tolerate the performance:
SELECT CONCAT_WS (" ", first_name, last_name) full_name
FROM YourTable
WHERE CONCAT_WS (" ", first_name, last_name) LIKE '%some string%';
A db table and an example would be easier to work with, but the simple case, should be something like the query below
I would make sure the search string is converted to lower case.
Notice that such a query on a large scale database might not be that quick
SELECT
*
FROM
users u
WHERE
LOWER(CONCAT(u.first_name,u.last_name)) LIKE '%{#search_string_here}%'
If you're looking at the format of your search term being the same with a firstname[space]lastname combination, you could do something like the below:
SELECT *
FROM Names
WHERE LEFT([Firstname] + ' ' + [lastname], LEN(#searchname)) = #searchname
This would allow you to search by the length of your search name. An example of how this could work is below:
CREATE TABLE Names
(
firstname NVARCHAR(100),
lastname NVARCHAR(100)
)
INSERT INTO Names VALUES
('John', 'Smith'), ('Jane', 'Doe'), ('Harry', 'Potter')
DECLARE #searchname NVARCHAR(100)
--John (Fist Name match only)
SET #searchname = 'John'
SELECT *
FROM Names
WHERE LEFT([Firstname] + ' ' + [lastname], LEN(#searchname)) = #searchname
--Jane D (First name + Initial Last name)
SET #searchname = 'Jane D'
SELECT *
FROM Names
WHERE LEFT([Firstname] + ' ' + [lastname], LEN(#searchname)) = #searchname
--H (Single character only in correct order)
SET #searchname = 'H'
SELECT *
FROM Names
WHERE LEFT([Firstname] + ' ' + [lastname], LEN(#searchname)) = #searchname
You can use this query:
SELECT first_name,last_name, CONCAT(CONCAT(first_name,' '),last_name) full_name
FROM User_table WHERE CONCAT(CONCAT(first_name,' '),last_name) LIKE '%string%'
Or:
SELECT first_name,last_name, CONCAT(first_name,last_name) full_name
FROM User_table WHERE CONCAT(fistName,lastName) LIKE '%string%'
For example, I create a table like you, and run this query get the result you want.
TB3:
Restult1:
Restult2:
Hope this helps.

Can CONTAINS Handle Table Columns that have NULL values?

I'm trying to do some query performance and I've been looking into applying a FULLTEXT INDEX as compared to using LIKE.
I have a database w/person information, i.e. FirstName, LastName, etc. where some of those columns are null.
When I try to use CONTAINS object, I'm getting this error message;
Null or empty full-text predicate
I've put in code to ensure the passed in #FirstName field is not null, and if a null was passed in then I've set it to ' "" ' like I've read elsewhere. I still get the error message. I'm starting to wonder if it's a problem because the index has columns that are null.
Does anyone know if that is the case, I've looked everywhere and I cannot find any information on this.
Here is the query. The #FirstNameLocal and #LastNameLocal are passed into this stored procedure. In this example, FirstName and/or LastName field data in the PersonTable could be null. I'm using SQL Server 2012 w/SP1. "Try to use" means when I try to run the query in SQL Management Studio.
SELECT DISTINCT LastName, FirstName, MiddleName, PersonId
FROM PersonTable
Where IsDeleted = 0
AND CONTAINS(FirstName, #FirstNameLocal)
AND CONTAINS(LastName, #LastNameLocal)
You could check whether your variable IS NULL or equals an empty string first. I think though that this will partially negate the benefit of full-text indexes and you should consider handling this differently (for instance with dynamic SQL).
SELECT DISTINCT LastName, FirstName, MiddleName, PersonId
FROM PersonTable
Where IsDeleted = 0
AND (ISNULL(#FirstNameLocal,'')='' OR CONTAINS(FirstName, #FirstNameLocal))
AND (ISNULL(#LastNameLocal,'')='' OR CONTAINS(LastName, #LastNameLocal));
If you would do this with dynamic SQL it would look something like this:
DECLARE #stmt NVARCHAR(4000);
SET #stmt=
N'SELECT DISTINCT LastName, FirstName, MiddleName, PersonId ' +
N'FROM PersonTable ' +
N'Where IsDeleted = 0' +
CASE WHEN ISNULL(#FirstNameLocal,'')=''
THEN N''
ELSE N' AND CONTAINS(FirstName, #FirstNameLocal)'
END +
CASE WHEN ISNULL(#LastNameLocal,'')=''
THEN N''
ELSE N' AND CONTAINS(LastName, #LastNameLocal)'
END + ';'
EXEC sp_executesql
#stmt,
N'#FirstNameLocal VARCHAR(256),#LastNameLocal VARCHAR(256)',
#FirstNameLocal,
#LastNameLocal;
The downside is that the statement is compiled again each time this script is run, but this will be small compared to the benefit of full-text indexes that can be used in this statement.
Always compare the Actual Execution Plans to choose which version is best.

select from table where #variable in(table column)

could u please correct this sqlserver query :
select * from messages where #DepartID In(MsgTo)
#DepartID is a session variable that contains the Department ID.
MsgTo is a column in messages table that contains list of values , ex. : '12','10','13','25' .. etc
i used this code :
cmd.CommandText = "select * from messages where #DepartID IN(MsgTo)"
cmd.Parameters.AddWithValue("#DepartID ", session("DepartID")) ' = 12 for example
Dim da As New SqlDataAdapter(cmd)
Dim dt As New DataTable
da.Fill(dt)
lbmsg.text = dt.Rows.Count.ToString ' returns 0 rows
sorry for my poor english
I think you're just having some syntax trouble. Have you declared the #DepartID variable in SQL? You need to make a comparison to an existing column in your WHERE clause. Like:
SELECT [ColumnName]
FROM [Table]
WHERE [ColumnName] = Value
If your department ID is a text-type column in SQL, you'll have to use single quotes on your input. You can use single quotes anyways in integers like IDs when you query them with an "IN" statement and it will work anyways. Try this:
SELECT *
FROM [messages]
WHERE [MsgTo] = #DepartID
So if you replace your #DepartID variable out with your value and then execute the statement, it will return all information for each row where your [MsgTo] column equals your #DepartID.
If you are passing multiple #DepartIDs, then you would have to pass a comma-delimited text list to the "IN" clause with your variable like the example below:
SELECT *
FROM [messages]
WHERE [MsgTo] IN ('1','5','3','12','30')
--Example where #DepartID = '1','5','3','12','30'
I'm not sure what language you're using to execute the SQL, but if this doesn't work, try encapsulating your SQL statement within an EXEC() like below:
EXEC(
SELECT *
FROM [messages]
WHERE [MsgTo] = #DepartID
)
If your MsgTo column contains a string list of values and you want to search through it for a single #DepartID, then use this code:
DECLARE #DepartID as INT; SET #DepartID = 12; --Hard coded example
SELECT *
FROM [messages]
WHERE [MsgTo] LIKE ('%,'''+#DepartID+''',%')

How to insert into a ForeignKey field using raw SQL?

I've got tables like the following (Django model definition, with a postgres database underlying it):
class Person(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=300)
class Owner(models.Model):
id = models.IntegerField()
person = models.ForeignKey(Person)
I use a Python script to set up my database from CSV files. The raw files list Owners with an integer id and an integer 'person' field, which maps to the integer in Person.id.
However, given that the 'person' column in Owner expects a Person object, how do I write a raw SQL string to insert value into Owner?
owner_id = 665
person_id = 330
sql_string = 'INSERT INTO owner (id, person) VALUES (' +
sql_string += owner_id + ', ' + ???? + ');'
You don't say why you need to do this in raw SQL. And I also don't understand why you're using structidx and person in the SQL when your PK field is called id - and the underlying column name for person is person_id. So your code should be:
sql_string = "INSERT INTO owner (`id`, `person_id`) VALUES (%s, %s)"
cursor = connection.cursor()
cursor.execute(sql_string, (665, 330))
Note that it's always good practice to use the Python db-api's quoting functionality, as I have here, to avoid SQL injection attacks.