如何改进此转换(int,myColumn)查询?

时间:2009-09-29 16:00:36

标签: sql-server

SQL Server 2000

背景

我有一张表,可以在我的课程表中存储有关特定课程的各种元数据。该表定义为:

create table course_prefs {
id int identity not null,
crs_nbr int references course (crs_nbr) not null,
fiscal_yr int not null,
group_name varchar(50) not null,
item_name varchar(50) null,
value varchar(100) not null)

并且有一些像这样的值:

ID    Crs_Nbr  Fiscal_Yr Group_Name        Item_Name     Value
1     5327     2007     StuAchievement     Qualifier     alg
2     5329     2007     StuAchievement     Qualifier     alg
153   2000     2003     LocUCInfo          543           F,0,0
154   2000     2003     LocUCInfo          542           F,0,0
6149  15746    2009     summerAttn         HS            coreClass
6150  12367    2009     summerAttn         HS            coreClass

...我已经开始从这个prefs表中查看视图以满足特定需求。但是,当我加入以下视图时:

CREATE    view loc_uc_info as

select cp.crs_nbr, c.abbr, cp.fiscal_yr, convert(int,cp.item_name) as loc_id
, substring(cp.value,1,1) as subject_area
, substring(cp.value,3,1) as honors
, substring(cp.value,5,1) as can_be_elective
from course_prefs cp join course c on cp.crs_nbr = c.crs_nbr
where cp.group_name = 'LocUCInfo'

问题
我收到以下错误消息:

  

语法错误将varchar值'HS'转换为数据类型为smallint的列。

我想要什么

我需要在loc_id列上编写一个连接到此视图的查询。这意味着父表和视图都在作为整数键入的列上连接。但是 - 视图在item_name列中有整数和char值,因此,我得到语法错误。我该怎么做才能解决这个问题?

我尝试的事情:

  1. 使用派生查询代替视图,我得到同样的错误。
  2. 仅基于uc_loc_info视图创建另一个视图。得到了同样的错误。
  3. 在我的loc_uc_info视图中使用isnumeric(cp.item_name)= 1 where子句来限制结果。

4 个答案:

答案 0 :(得分:2)

不确定你想要的结果是什么,但使用的是什么:

case when isnumeric(cp.item_name) = 1 then convert(int,cp.item_name) else null end

而不仅仅是你的

convert(int,cp.item_name)

答案 1 :(得分:1)

注意:在第一条消息下面添加了最终工作代码。

您能否在视图中详细解释您想要完成的这一行?

convert(int, cp.item_name) as loc_id,

Penfold的建议似乎很好。

这是工作代码。 (是的,它使用了2005“sys。”表。将它们转换为2000年运行。)它用Penfold的建议替换了你的“loc_id”列。

代码

IF EXISTS (SELECT * FROM sys.tables WHERE name = 'Course')
    DROP TABLE dbo.Course
GO
CREATE TABLE dbo.Course (
    ID          int             not null,   -- identity
    Abbr        varchar(5)      not null,
    Crs_Nbr     int             not null    --references course (crs_nbr)
)
GO
IF EXISTS (SELECT * FROM sys.tables WHERE name = 'Course_Prefs')
    DROP TABLE dbo.Course_Prefs
GO
CREATE TABLE dbo.Course_Prefs (
    ID          int             not null,   -- identity
    Crs_Nbr     int             not null,   --references course (crs_nbr)
    Fiscal_Yr   int             not null,
    Group_Name  varchar(50)     not null,
    Item_Name   varchar(50)     null,
    Value       varchar(100)    not null
)
GO
INSERT INTO dbo.Course VALUES (1, 'Crs1', 5327)
INSERT INTO dbo.Course VALUES (2, 'Crs2', 5329)
INSERT INTO dbo.Course VALUES (3, 'Crs3', 2000)
INSERT INTO dbo.Course VALUES (4, 'Crs4', 15746)
INSERT INTO dbo.Course VALUES (5, 'Crs5', 12367)
GO

INSERT INTO dbo.Course_Prefs VALUES (1, 5327, 2007, 'StuAchievement', 'Qualifier', 'alg')
INSERT INTO dbo.Course_Prefs VALUES (2, 5329, 2007, 'StuAchievement', 'Qualifier', 'alg')
INSERT INTO dbo.Course_Prefs VALUES (153, 2000, 2003, 'LocUCInfo', '543', 'F,0,0')
INSERT INTO dbo.Course_Prefs VALUES (154, 2000, 2003, 'LocUCInfo', '542', 'F,0,0')
INSERT INTO dbo.Course_Prefs VALUES (6149, 15746, 2009, 'summerAttn', 'HS', 'coreClass')
INSERT INTO dbo.Course_Prefs VALUES (6150, 12367, 2009, 'summerAttn', 'HS', 'coreClass')
GO

SELECT * FROM dbo.Course
SELECT * FROM dbo.Course_Prefs
GO

IF EXISTS (SELECT * FROM sys.views WHERE name = 'Loc_uc_Info')
    DROP VIEW dbo.Loc_uc_Info
GO
CREATE VIEW dbo.Loc_uc_Info AS
SELECT
    cp.crs_nbr,
    c.abbr,
    cp.fiscal_yr,
    case when isnumeric(cp.item_name) = 1 then convert(int,cp.item_name) else null end  AS loc_id,
    --convert(int, cp.item_name) as loc_id,
    substring(cp.value, 1, 1) as subject_area,
    substring(cp.value, 3, 1) as honors,
    substring(cp.value, 5, 1) as can_be_elective
FROM dbo.Course_Prefs   AS cp
JOIN dbo.Course         AS c ON cp.crs_nbr = c.crs_nbr
--WHERE cp.group_name = 'LocUCInfo'
GO
SELECT * FROM dbo.Loc_uc_Info
GO

结果

         ID Abbr      Crs_Nbr
----------- ----- -----------
          1 Crs1         5327
          2 Crs2         5329
          3 Crs3         2000
          4 Crs4        15746
          5 Crs5        12367

         ID     Crs_Nbr   Fiscal_Yr Group_Name                                         Item_Name                                          Value
----------- ----------- ----------- -------------------------------------------------- -------------------------------------------------- ----------------------------------------------------------------------------------------------------
          1        5327        2007 StuAchievement                                     Qualifier                                          alg
          2        5329        2007 StuAchievement                                     Qualifier                                          alg
        153        2000        2003 LocUCInfo                                          543                                                F,0,0
        154        2000        2003 LocUCInfo                                          542                                                F,0,0
       6149       15746        2009 summerAttn                                         HS                                                 coreClass
       6150       12367        2009 summerAttn                                         HS                                                 coreClass

    crs_nbr abbr    fiscal_yr      loc_id subject_area honors can_be_elective
----------- ----- ----------- ----------- ------------ ------ ---------------
       5327 Crs1         2007        NULL a            g      
       5329 Crs2         2007        NULL a            g      
       2000 Crs3         2003         543 F            0      0
       2000 Crs3         2003         542 F            0      0
      15746 Crs4         2009        NULL c            r      C
      12367 Crs5         2009        NULL c            r      C

编辑:忘记包含Penfold的代码。


基于HLGEM建议的最终工作代码

IF EXISTS (SELECT * FROM sys.tables WHERE name = 'Course')
    DROP TABLE dbo.Course
GO
CREATE TABLE dbo.Course (
    ID          int             not null,   -- identity
    Abbr        varchar(5)      not null,
    Crs_Nbr     int             not null    --references course (crs_nbr)
)
GO
IF EXISTS (SELECT * FROM sys.tables WHERE name = 'Course_Prefs')
    DROP TABLE dbo.Course_Prefs
GO
CREATE TABLE dbo.Course_Prefs (
    ID          int             not null,   -- identity
    Crs_Nbr     int             not null,   --references course (crs_nbr)
    Fiscal_Yr   int             not null,
    Group_Name  varchar(50)     not null,
    Item_Name   varchar(50)     null,
    Value       varchar(100)    not null
)
GO
INSERT INTO dbo.Course VALUES (1, 'Crs1', 5327)
INSERT INTO dbo.Course VALUES (2, 'Crs2', 5329)
INSERT INTO dbo.Course VALUES (3, 'Crs3', 2000)
INSERT INTO dbo.Course VALUES (4, 'Crs4', 15746)
INSERT INTO dbo.Course VALUES (5, 'Crs5', 12367)
GO

INSERT INTO dbo.Course_Prefs VALUES (1,     5327, 2007, 'StuAchievement', 'Qualifier', 'alg')
INSERT INTO dbo.Course_Prefs VALUES (2,     5329, 2007, 'StuAchievement', 'Qualifier', 'alg')
INSERT INTO dbo.Course_Prefs VALUES (153,   2000, 2003, 'LocUCInfo',      '543',       'F,0,0')
INSERT INTO dbo.Course_Prefs VALUES (154,   2000, 2003, 'LocUCInfo',      '542',       'F,0,0')
INSERT INTO dbo.Course_Prefs VALUES (6149, 15746, 2009, 'summerAttn',     'HS',        'coreClass')
INSERT INTO dbo.Course_Prefs VALUES (6150, 12367, 2009, 'summerAttn',     'HS',        'coreClass')
GO

SELECT * FROM dbo.Course
SELECT * FROM dbo.Course_Prefs
GO

IF EXISTS (SELECT * FROM sys.views WHERE name = 'Loc_uc_Info')
    DROP VIEW dbo.Loc_uc_Info
GO
CREATE VIEW dbo.Loc_uc_Info AS
SELECT
    cp.crs_nbr,
    c.abbr,
    cp.fiscal_yr,
    convert(int,
        case
            when isnumeric(cp.item_name) = 1 then cp.item_name
            else 0
        end
    ) as loc_id,
    substring(cp.value, 1, 1)   as subject_area,
    substring(cp.value, 3, 1)   as honors,
    substring(cp.value, 5, 1)   as can_be_elective
FROM dbo.Course_Prefs   AS cp
JOIN dbo.Course         AS c ON cp.crs_nbr = c.crs_nbr
WHERE cp.group_name = 'LocUCInfo'
GO
SELECT * FROM dbo.Loc_uc_Info
GO

答案 2 :(得分:1)

试试这个:

convert(int,case when isnumeric(cp.item_name)= 1 then cp.item_name else null end as loc_id

如果不起作用,请尝试:

convert(int,case when isnumeric(cp.item_name)= 1 then cp.item_name else 0 end as loc_id

我个人认为你的基本设计存在很多缺陷,你不应该在同一列中有数字和字符数据。你也不应该用逗号分隔值。

我不是观点的粉丝,尤其是那些被置于观点之上的观点,因为当它们无法正确编入索引时会破坏性能。

答案 3 :(得分:0)

从头到尾:创建两个视图怎么样?

在没有转换的情况下执行连接,在第一个视图上执行转换的另一个。

由于第一个视图只应包含Item_Name中的数字(即543和542),因此不会出现转换错误。