Introduction first, question at the end. Please read carefully!
I have a master-detail relation between two tables:
CREATE TABLE [dbo].[LookupAttributes] (
[Id] int IDENTITY (1, 1) NOT NULL,
[Name] nvarchar (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL) ;
ALTER TABLE [dbo].[LookupAttributes] ADD CONSTRAINT [PK_LookupAttributes] PRIMARY KEY ([Identity]) ;
CREATE TABLE [dbo].[Lookup] (
[Id] int IDENTITY (1, 1) NOT NULL,
[LookupAttributesLink] int NOT NULL,
[Code] nvarchar (20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Value] nvarchar (80) COLLATE SQL_Latin1_General_CP1_CI_AS NULL) ;
ALTER TABLE [dbo].[Lookup] ADD CONSTRAINT [IX_Lookup] UNIQUE ([LookupAttributenLink], [Code]) ;
(There are more fields and indices in both tables but these are the ones that matter...)
The project I'm working on is meant to maintain data in 50+ tables, and every week this data is exported to XML to be used by some desktop application as source data. While I wanted to make this a pretty-looking application, it just needed to be done fast, thus I use a Dynamic Data Site so the data can be maintained. It works just fine, except for this table...
As it turns out, there are 600 different lookup records that share the same code, but different attributes. The DDS displays attribute and code correctly in the list of lookup records so there never was any confusion about which lookup record someone was editing. And this has been in use for over 2 years now.
Now the problem: A new table "Lookup-Override" has been added which links to the [Id] field of the Lookup table. Each record in this new table thus displays the [Code] field, but since [Code] isn't unique, it's unclear which Override record belongs to which Lookup record.
To solve this, I need to display more information from the Lookup record. Since the only unique set of fields is the attribute plus code, I need to display both. But displaying [LookupAttributesLink]+[Code] isn't an option either, since [LookupAttributesLink] is just a number.I need the DDS to display [Attributes].[LookupAttributesLink]+[Lookup].[Code] in a single column. Question is: how?I've considered adding a calculated field to the Lookup table, but I cannot get the attribute name that way.I could create a special page to maintain this table but I don't like that solution either, since it "breaks" the DDS principle in my opinion. I'm trying to avoid such pages.So, any other possibilities to get the site display both attribute name and lookup code in the override table?
The most interesting solution would be by using a calculated field which could retrieve the attribute name. How to do that?
Solved it myself! See answer below, which works just fine.
Found it! I had to do a few things:
CREATE FUNCTION LookupName (
#Attr int,
#Code nvarchar(255)
) RETURNS nvarchar(1000)
AS
BEGIN
DECLARE #Name nvarchar(1000)
SELECT #Name = Name
FROM [dbo].[LookupAttributes]
WHERE [Id]=#Attr;
RETURN #Name + '/' + #Code;
END
GO
ALTER TABLE [dbo].[lookup] ADD [Name] AS [dbo].[LookupName]([LookupAttributesLink], [Code])
GO
This will add an additional calculated field to the table which uses a function to calculate the proper name. I then had to add some metadata for the lookup table:
[MetadataType(typeof(LookupMetadata))]
public partial class Lookup { }
[DisplayColumn("Name", "Name")]
[DisplayName("Lookup")]
public class LookupMetadata
{
[ScaffoldColumn(false)]
public int Id;
[ScaffoldColumn(false)]
public object Name;
}
This will hide the Name column from the Lookup table itself, but it makes it visible for the Override table. (And it will be used to display the proper value.
Done this, solved the problem! Quite easy, actually. :-)
Related
I am first creating a table in which I have 6 headers/columns, then I add a column in there and set a default value for that new column. The part I'm trying to modify is that new column which I set. I have some places where the default value would change - based on a different column that is purely form that data I imported.
My code is as follows:
SET GLOBAL local_infile=1;
CREATE TABLE audio(
File_Name CHAR(4) PRIMARY KEY,
File_Subdirectory CHAR(50),
....,
....,
....,
....,
);
-- Created table with the headers described above (left out 4 column names)
LOAD DATA LOCAL INFILE 'audio.csv'
INTO TABLE audio
FIELDS TERMINATED BY ',';
-- Loaded data into the right columns, even when I check with SELECT * FROM audio looks good
ALTER TABLE audio ADD COLUMN Microphone VARCHAR(15) DEFAULT 'Forward' AFTER File_Directory
-- Successful added a column after File_Directory with header Microphone and default was Forward for all entries/rows.
IF (SELECT File_Directory FROM audio WHERE File_Driectory = 'Home')
SET Microphone = 'Not Forward'
END IF;
-- Here I want to change the Microphone column (3rd column now - previously added and set default to be 'forward') to be 'Not Forward' if the File_Directory column has variable/entry to be home.
Also, if I do the following I get the entries which I am looking for and which I would like to change that third column. It prints out the column with multiple rows that have 'Home' written as the entry. These rows are the ones I'd like to change that new column I added, I want to change it from default 'forward' to 'not forward'.
SELECT File_Directory FROM audio WHERE File_Driectory = 'Home'
My problem is with the last statement since I am not able to SET or change the entry to that third column... it's not that I can't, I am not sure what I am doing wrong with the IF statement. I hope the code I provided is enough to give me a quick solution. I left out the other 4 column names since they are not relevant nor do I do anything in them. Again I load data from a csv, successfully add a column with a header/and default field (which is the majority), I just need to change the few places that new column needs to have a different name/entry.
Any suggestions would be helpful! Thank you!
I was able to solve this easily without even using an IF statement. I used the UPDATE command.
UPDATE audio SET Microphone = 'Not forward' WHERE File_Directory = 'Home'
This is my 5th day learning SQL on mySQL.
I don't understand why the system tells me the following is an error.
My code is:
CREATE TABLE elements(
Name VARCHAR(20),
Symbol VARCHAR(2) PRIMARY KEY,
AtomicNumber TINYINT,
AtomicMass DEC(4,2) -- ending doesn't need , similar to SAS
);
INSERT INTO elements
VALUES ('Actinium','Ac',89,227);
-- here we want to modify the field type of the existing table because Aluminum has decimal #'s in mass
ALTER TABLE elements
MODIFY AtomicMass DECIMAL(9,3);
-- Q: I do not understand this why this is an syntax error.
System Message: "Syntax error: unexpected 'DECIMAL(decimal)'"
It runs and changes the field constraint but the error message is still there.
Additional Question(utterly noob question,please tolerate me): How do you put 'space' in a name of a column? Like now I'm using "AtomicNumber" but I really want "Atomic Number."
Thanks! :)
Consult https://dev.mysql.com/doc/refman/5.6/en/alter-table.html.
You are missing COLUMN.
ALTER TABLE elements
MODIFY COLUMN `AtomicMass` DECIMAL(9,3);
The name of the MySQL data type is DECIMAL, not DEC. So your original table definition statement should look like this:
CREATE TABLE elements(
Name VARCHAR(20),
Symbol VARCHAR(2) PRIMARY KEY,
AtomicNumber TINYINT,
AtomicMass DECIMAL(4,2) -- ending doesn't need , similar to SAS
);
Your modification should look like this:
ALTER TABLE elements
CHANGE COLUMN AtomicMass AtomicMass DECIMAL(10,2)
But, you should consider using FLOAT or DOUBLE rather than DECIMAL for values like atomic weight. Two decimal places of precision isn't very representative of the actual scientific truth.
Finally if you want to wrap your column names in backticks like this
`Atomic Mass`
everywhere you use them, you can put spaces in column names. But this will drive you crazy when you're writing code, I suspect.
I have a table with column names like so:
BLAH_Q1_NAME, BLAH_BLAH_Q2_AGE, BLAH_UGLY_BLAH_Q3_DATE_OF_BIRTH, etc.
I want to be able to change the column names to strip away all of the name before the "Q#" portion, such that I end up with column names that look like so:
Q1_NAME, Q2_AGE, Q3_DATE_OF_BIRTH, etc.
There are 40+ variables in this table, which prohibits me simply doing this manually. (I hope!!) Is there any way to do this in MySQL? Thanks!
There's no MySQL command to let you quickly rename 40 columns, but you can just grab a random scripting language to help you write a query to do that for you.
$ perl -le'print "alter table MyTable ". (join ", ", map { "change BLAH_Q${_}_NAME Q${_}_NAME INT" } 1..40)'
(truncated) output:
alter table MyTable change BLAH_Q1_NAME Q1_NAME INT, change BLAH_Q2_NAME Q2_NAME INT, change BLAH_Q3_NAME Q3_NAME INT, change BLAH_Q4_NAME Q4_NAME INT, change BLAH_Q5_NAME Q5_NAME INT
I had to bring in a whole bunch of tables from CSV files. A lot of these files had column that were INT but had null values. To speed up the import I just made all of the column VARCHAR. Now I have all this data in the tables but need to change the type. I'm able to do this in the MySQL workbench except for one problem -- It error's because of the null/blank values. Is there some sort of SQL magic that will allow me to convert these column types and ignore the nulls or replace them with the correct 'null value' for that data type?
You can update the columns to set blank fields as NULL as follows:
UPDATE mytable SET mycolumn=NULL WHERE TRIM(mycolumn,' ')='';
Then do your normal table alters as follows:
ALTER TABLE mytable MODIFY mycolumn VARCHAR(255);
The 'DEFAULT NULL' is optional as fields by default allow null. This should allow you to convert the columns to whatever data types you wish without any problem except in the case where there is mixed data -- such as numbers, and strings, and you wish to make that column FLOAT.
The above example also does not take into account removing carriage returns, etc, in the event that a column contains a "\n" or "\r\n" and nothing else, it will not set it to NULL, but you can modify the "TRIM(mycolumn, ' ')" to meet those requirements if you have them : aka ...
UPDATE mytable SET mycolumn=NULL WHERE TRIM(mycolumn,"\n")='';
I have a hierarchyid column defined on a table in SQL Server 2008
Let us say that in the first row, the hierarchyid is '/1/7/1/'
Let us say that in the second row, the hierarchyid is '/1/10/1/'
If I sort by hierarchyid ASC , then I will see the second row, and then the first row. (The sorting will be sort by String, and '10'<'7')
However I have (for compatability reasons with a different system) a wish to see the first row first, and then the second row (I.e. sort by int, and 7<10)
I have solved the problem, by defining a second hierarchyid column, and then setting it to be the same as the first hierarchyid column, but replacing all inside slashes with dots, and then doing a sort by this.
I just wondered if there was a more elegant way.
I know this is a fairly old question, but it was first result in Google so thought I'd add an actual answer in case someone else comes across this. Without seeing the SQL being used it's hard to be 100% but I suspect that the OP is returning the hierarchy Id as a string and sorting on that rather than sorting on the hierarchy id itself:
EG..
declare #results table (Id int, Hierarchy hierarchyId)
-- :
-- Add your data here
-- :
-- This will not work as it's ordering a string
select Id, Hierarchy.ToString() as SortOrder from #results order by SortOrder
-- This will work as it's ordering the hierarchy id
select Id, Hierarchy.ToString() as SortOrder from #results order by Hierarchy
you would need to isolate whats between the two "/" and order by it.
you can use this function: http://www.sqlusa.com/bestpractices2005/nthindex/
to get the nth Index on a string, so
declare #aux_str varchar(50)
set #aux_str='/1/7/3/'
select dbo.fnNthIndex(#aux_str,'/',2)
returns 3. Them you have to find out the position of the third "/" and get what's between it.
Its not hard, but its quite a lot of work